Add autoplug/manual mode in VoIP. Fix memory leaks. 94/50194/1
authorVyacheslav Valkovoy <v.valkovoy@samsung.com>
Mon, 26 Oct 2015 18:05:33 +0000 (20:05 +0200)
committerVyacheslav Valkovoy <v.valkovoy@samsung.com>
Mon, 26 Oct 2015 18:06:11 +0000 (20:06 +0200)
Change-Id: Ib8f84de32b0bb24b738f9d84d29a7247a3e70bd3
Signed-off-by: Vyacheslav Valkovoy <v.valkovoy@samsung.com>
include/media_streamer_gst.h
include/media_streamer_priv.h
include/media_streamer_util.h
src/media_streamer_gst.c
src/media_streamer_node.c
src/media_streamer_priv.c
src/media_streamer_util.c
test/media_streamer_test.c

index a9cc18e..de09a51 100755 (executable)
@@ -111,7 +111,7 @@ GstElement *__ms_rtp_element_create(media_streamer_node_s *ms_node);
 
 /**
  * @brief Find Udp elements into rtp container by name.
- *
+ *        It returns elements with increased ref count.
  * @since_tizen 3.0
  */
 gboolean __ms_get_rtp_elements(media_streamer_node_s *ms_node, GstElement **rtp_elem,
index 6fcae1d..9d4b4c1 100755 (executable)
@@ -68,6 +68,7 @@ typedef struct {
 
        GHashTable *nodes_table;
        GMutex mutex_lock;
+       GList *autoplug_sig_list;
 
        GstBus *bus;
        guint bus_watcher;
@@ -102,6 +103,8 @@ typedef struct {
 
        gboolean linked_by_user;
 
+       GList *sig_list;
+
        ms_node_set_param set_param;
        void *callbacks_structure;
 } media_streamer_node_s;
index dc87448..b8d3af9 100755 (executable)
@@ -19,6 +19,7 @@
 
 #include <stdlib.h>
 #include <glib.h>
+#include <gst/gst.h>
 #include <dlog.h>
 #include <iniparser.h>
 
@@ -97,6 +98,15 @@ typedef struct __media_streamer_ini {
 
 } media_streamer_ini_t;
 
+/**
+ * @brief Media Streamer signal structure.
+ *
+ * @since_tizen 3.0
+ */
+typedef struct {
+       GObject* obj;
+       gulong signal_id;
+} media_streamer_signal_s;
 
 /*Test elements*/
 #define DEFAULT_VIDEO_TEST_SOURCE           "videotestsrc"
@@ -254,6 +264,22 @@ const gchar *__ms_convert_mime_to_rtp_format(media_format_mimetype_e mime);
  */
 media_format_mimetype_e __ms_convert_string_format_to_mime(const char *format_type);
 
+/**
+ * @brief Creates Media streamer signal structure,
+ *        connects it to object and appends it to signal list.
+ *
+ * @since_tizen 3.0
+ */
+void __ms_signal_create(GList **sig_list, GstElement *obj, const char *sig_name, GCallback cb, gpointer user_data);
+
+/**
+ * @brief Disconnects signal from object and
+ * destroys Media streamer signal object.
+ *
+ * @since_tizen 3.0
+ */
+void __ms_signal_destroy(void *data);
+
 #ifdef __cplusplus
 }
 #endif
index db48298..6c9249b 100755 (executable)
@@ -55,50 +55,46 @@ static int __ms_add_no_target_ghostpad(GstElement * gst_bin, const char *ghost_p
        return ret;
 }
 
-static int __ms_add_ghostpad(GstElement * gst_element, const char *pad_name, GstElement * gst_bin, const char *ghost_pad_name)
+static gboolean __ms_add_ghostpad(GstElement * gst_element, const char *pad_name, GstElement * gst_bin, const char *ghost_pad_name)
 {
-       ms_retvm_if(!gst_element || !pad_name || !ghost_pad_name || !gst_bin, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+       ms_retvm_if(!gst_element || !pad_name || !ghost_pad_name || !gst_bin, FALSE, "Handle is NULL");
 
-       int ret = MEDIA_STREAMER_ERROR_NONE;
+       gboolean ret = FALSE;
 
        GstPad *ghost_pad = NULL;
-       gchar *bin_name = gst_element_get_name(gst_bin);
-
-       gchar *element_name = gst_element_get_name(gst_element);
        GstPad *element_pad = gst_element_get_static_pad(gst_element, pad_name);
-       if (!element_pad) {
-               /*maybe it is request pad */
+
+       if (element_pad == NULL) {
+               /* maybe it is request pad */
                element_pad = gst_element_get_request_pad(gst_element, pad_name);
        }
-       if (element_pad != NULL) {
-               ghost_pad = gst_ghost_pad_new(ghost_pad_name, element_pad);
-               gst_pad_set_active(ghost_pad, TRUE);
 
-               gst_element_add_pad(GST_ELEMENT(gst_bin), ghost_pad);
-               ms_info("Added %s ghostpad from [%s] into [%s]", pad_name, element_name, bin_name);
-               MS_SAFE_UNREF(element_pad);
-               MS_SAFE_GFREE(element_name);
+       ghost_pad = gst_ghost_pad_new(ghost_pad_name, element_pad);
+       gst_pad_set_active(ghost_pad, TRUE);
+
+       ret = gst_element_add_pad(GST_ELEMENT(gst_bin), ghost_pad);
 
-               ret = MEDIA_STREAMER_ERROR_NONE;
+       if (ret) {
+               ms_info("Added %s ghostpad from [%s] into [%s]", pad_name,
+                                               GST_ELEMENT_NAME(gst_element), GST_ELEMENT_NAME(gst_bin));
        } else {
-               ms_error("Error: element [%s] does not have valid [%s] pad for adding into [%s] bin", element_name, pad_name, bin_name);
-               ret = MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+               ms_error("Error: element [%s] does not have valid [%s] pad for adding into [%s] bin",
+                                               GST_ELEMENT_NAME(gst_element), pad_name, GST_ELEMENT_NAME(gst_bin));
        }
 
-       MS_SAFE_GFREE(bin_name);
+       MS_SAFE_UNREF(element_pad);
        return ret;
 }
 
 static GObject *__ms_get_property_owner(GstElement * element, const gchar * key, GValue * value)
 {
-       GParamSpec *param;
+       GParamSpec *param = NULL;
        GObject *obj = NULL;
 
        if (GST_IS_CHILD_PROXY(element)) {
                int i;
                int childs_count = gst_child_proxy_get_children_count(GST_CHILD_PROXY(element));
 
-               param = NULL;
                for (i = 0; (i < childs_count) && (param == NULL); ++i) {
                        obj = gst_child_proxy_get_child_by_index(GST_CHILD_PROXY(element), i);
                        param = g_object_class_find_property(G_OBJECT_GET_CLASS(obj), key);
@@ -124,21 +120,19 @@ static GObject *__ms_get_property_owner(GstElement * element, const gchar * key,
 
 gboolean __ms_element_set_property(GstElement * element, const char *key, const gchar * param_value)
 {
-       gchar *element_name = gst_element_get_name(element);
-       GValue value = G_VALUE_INIT;
-
        char *init_name = NULL;
        int pint = 0;
-       gboolean bool_val = false;
+       gboolean bool_val = FALSE;
+       gboolean ret = FALSE;
 
        __ms_node_check_param_name(element, TRUE, key, &init_name);
 
        if (init_name) {
+               GValue value = G_VALUE_INIT;
                GObject *obj = __ms_get_property_owner(element, init_name, &value);
 
                if (obj == NULL) {
-                       ms_debug("Element [%s] does not have property [%s].", element_name, init_name);
-                       MS_SAFE_GFREE(element_name);
+                       ms_debug("Element [%s] does not have property [%s].", GST_ELEMENT_NAME(element), init_name);
                        return FALSE;
                }
 
@@ -235,15 +229,14 @@ gboolean __ms_element_set_property(GstElement * element, const char *key, const
                        ms_info("Set string value: [%s]", g_value_get_string(&value));
                } else {
                        ms_info("Got unknown type with param->value_type [%lu]", G_VALUE_TYPE(&value));
-                       return FALSE;
+                       ret =  FALSE;
                }
+               g_value_unset(&value);
        } else {
-               ms_info("Can not set parameter [%s] in the node [%s]\n", key, gst_element_get_name(element));
+               ms_info("Can not set parameter [%s] in the node [%s]", key, GST_ELEMENT_NAME(element));
        }
 
-       MS_SAFE_GFREE(element_name);
-
-       return TRUE;
+       return ret;
 }
 
 /* This unlinks from its peer and ghostpads on its way */
@@ -471,17 +464,17 @@ gboolean __ms_feature_filter(GstPluginFeature * feature, gpointer data)
 
 GstElement *__ms_create_element_by_registry(GstPad * src_pad, const gchar * klass_name)
 {
-       GList *factories;
        const GList *pads;
        GstElement *next_element = NULL;
 
        GstCaps *new_pad_caps = gst_pad_query_caps(src_pad, NULL);
 
-       factories = gst_registry_feature_filter(gst_registry_get(), (GstPluginFeatureFilter) __ms_feature_filter, FALSE, NULL);
-       factories = g_list_sort(factories, (GCompareFunc) __ms_factory_rank_compare);
-
-       for (; factories != NULL; factories = factories->next) {
-               GstElementFactory *factory = GST_ELEMENT_FACTORY(factories->data);
+       GList *factories = gst_registry_feature_filter(gst_registry_get(),
+                                               (GstPluginFeatureFilter)__ms_feature_filter, FALSE, NULL);
+       factories = g_list_sort(factories, (GCompareFunc)__ms_factory_rank_compare);
+       GList *factories_iter = factories;
+       for (; factories_iter != NULL ; factories_iter = factories_iter->next) {
+               GstElementFactory *factory = GST_ELEMENT_FACTORY(factories_iter->data);
 
                if (g_strrstr(gst_element_factory_get_klass(GST_ELEMENT_FACTORY(factory)), klass_name)) {
                        for (pads = gst_element_factory_get_static_pad_templates(factory); pads != NULL; pads = pads->next) {
@@ -539,9 +532,9 @@ GstElement *__ms_link_with_new_element(GstElement * previous_element, GstElement
                        if (!gst_pad_is_linked(sink_pad)) {
                                if (!strncmp(new_pad_type, GST_PAD_NAME(sink_pad), 5)) {
                                        if (gst_element_link_pads_filtered(previous_element, "src", new_element, GST_PAD_NAME(sink_pad), NULL))
-                                               ms_info("Succeeded to link [%s] -> [%s]\n", GST_ELEMENT_NAME(previous_element), GST_ELEMENT_NAME(new_element));
+                                               ms_info("Succeeded to link [%s] -> [%s]", GST_ELEMENT_NAME(previous_element), GST_ELEMENT_NAME(new_element));
                                        else
-                                               ms_error("Failed to link [%s] -> [%s]\n", GST_ELEMENT_NAME(previous_element), GST_ELEMENT_NAME(new_element));
+                                               ms_error("Failed to link [%s] -> [%s]", GST_ELEMENT_NAME(previous_element), GST_ELEMENT_NAME(new_element));
                                }
                        }
                        MS_SAFE_UNREF(prev_elem_sink_pad);
@@ -556,9 +549,9 @@ GstElement *__ms_link_with_new_element(GstElement * previous_element, GstElement
                gboolean ret = gst_element_link_pads_filtered(previous_element, NULL, new_element, NULL, NULL);
 
                if (ret)
-                       ms_info("Succeeded to link [%s] -> [%s]\n", GST_ELEMENT_NAME(previous_element), GST_ELEMENT_NAME(new_element));
+                       ms_info("Succeeded to link [%s] -> [%s]", GST_ELEMENT_NAME(previous_element), GST_ELEMENT_NAME(new_element));
                else
-                       ms_error("Failed to link [%s] and [%s] \n", GST_ELEMENT_NAME(previous_element), GST_ELEMENT_NAME(new_element));
+                       ms_error("Failed to link [%s] and [%s]", GST_ELEMENT_NAME(previous_element), GST_ELEMENT_NAME(new_element));
        }
        return new_element;
 }
@@ -643,13 +636,13 @@ gint __ms_decodebin_autoplug_select(GstElement * bin, GstPad * pad, GstCaps * ca
        factory_name = GST_OBJECT_NAME(factory);
        klass = gst_element_factory_get_metadata(factory, GST_ELEMENT_METADATA_KLASS);
 
-       ms_debug("Decodebin: found new element [%s] to link [%s]\n\n", factory_name, klass);
+       ms_debug("Decodebin: found new element [%s] to link [%s]", factory_name, klass);
 
        if ((g_strrstr(klass, "Codec/Decoder/Video"))) {
 
                /* Skip Video4Linux decoders */
                if (g_strrstr(factory_name, "v4l2video")) {
-                       ms_debug("Decodebin: skipping [%s] by not required\n", factory_name);
+                       ms_debug("Decodebin: skipping [%s] by not required", factory_name);
                        return GST_AUTOPLUG_SELECT_SKIP;
                }
 
@@ -674,7 +667,7 @@ void __decodebin_newpad_streamer_cb(GstElement * decodebin, GstPad * new_pad, gp
        GstStructure *new_pad_struct = NULL;
        const gchar *new_pad_type = NULL;
 
-       ms_info("Received new pad '%s' from [%s]\n", GST_PAD_NAME(new_pad), GST_ELEMENT_NAME(decodebin));
+       ms_info("Received new pad '%s' from [%s]", GST_PAD_NAME(new_pad), GST_ELEMENT_NAME(decodebin));
 
        /* Check the new pad's type */
        new_pad_caps = gst_pad_query_caps(new_pad, 0);
@@ -759,7 +752,7 @@ void __decodebin_newpad_cb(GstElement * decodebin, GstPad * new_pad, gpointer us
                found_element = __ms_combine_next_element(found_element, MEDIA_STREAMER_SINK_KLASS, NULL, NULL);
 
                if (!found_element)
-                       ms_error("Could not link to sink element \n");
+                       ms_error("Could not link to sink element");
        }
 
        gst_caps_unref(new_pad_caps);
@@ -808,7 +801,7 @@ void __decodebin_newpad_client_cb(GstElement * decodebin, GstPad * new_pad, gpoi
        found_element = __ms_combine_next_element(found_element, MEDIA_STREAMER_SINK_KLASS, NULL, NULL);
 
        if (!found_element)
-               ms_error("Could not link to sink element \n");
+               ms_error("Could not link to sink element");
 
        gst_caps_unref(new_pad_caps);
 }
@@ -843,12 +836,15 @@ static gboolean __ms_sink_bin_prepare(media_streamer_node_s * ms_node, GstElemen
 
        if (!found_element) {
                if (decodebin_usage) {
-
                        found_element = __ms_element_create("decodebin", NULL);
-                       gst_bin_add_many((GstBin *) sink_bin, found_element, NULL);
+                       __ms_bin_add_element(sink_bin, found_element, FALSE);
                        gst_element_sync_state_with_parent(found_element);
-                       g_signal_connect(found_element, "pad-added", G_CALLBACK(__decodebin_newpad_client_cb), (gpointer) ms_node);
-                       g_signal_connect(found_element, "autoplug-select", G_CALLBACK(__ms_decodebin_autoplug_select), NULL);
+
+                       __ms_signal_create(&ms_node->parent_streamer->autoplug_sig_list, found_element, "pad-added",
+                                               G_CALLBACK(__decodebin_newpad_client_cb), (gpointer)ms_node);
+                       __ms_signal_create(&ms_node->parent_streamer->autoplug_sig_list, found_element, "autoplug-select",
+                                               G_CALLBACK(__ms_decodebin_autoplug_select), NULL);
+
                        previous_element = __ms_link_with_new_element(previous_element, found_element, NULL);
                        __ms_element_set_state(found_element, GST_STATE_PLAYING);
 
@@ -900,20 +896,17 @@ static gboolean __ms_sink_bin_prepare(media_streamer_node_s * ms_node, GstElemen
 
 static void __ms_rtpbin_pad_added_cb(GstElement * src, GstPad * new_pad, gpointer user_data)
 {
-       gchar *new_pad_name = NULL;
-       gchar *src_element_name = NULL;
+       ms_debug("Pad [%s] added on [%s]", GST_PAD_NAME(new_pad), GST_ELEMENT_NAME(src));
 
        media_streamer_node_s *ms_node = (media_streamer_node_s *) user_data;
        ms_retm_if(ms_node == NULL, "Handle is NULL");
 
-       new_pad_name = gst_pad_get_name(new_pad);
-       src_element_name = gst_element_get_name(src);
-       ms_debug("Pad [%s] added on [%s]\n", new_pad_name, src_element_name);
+       if (g_str_has_prefix(GST_PAD_NAME(new_pad), "recv_rtp_src")) {
+               media_streamer_s *ms_streamer = ms_node->parent_streamer;
+               ms_retm_if(ms_streamer == NULL, "Node's parent streamer handle is NULL");
 
-       GstPad *target_pad = gst_ghost_pad_get_target(GST_GHOST_PAD(new_pad));
-       GstCaps *src_pad_caps = gst_pad_query_caps(target_pad, NULL);
-
-       if (ms_node->parent_streamer && !gst_caps_is_any(src_pad_caps)) {
+               GstPad *target_pad = gst_ghost_pad_get_target(GST_GHOST_PAD(new_pad));
+               GstCaps *src_pad_caps = gst_pad_query_caps(target_pad, NULL);
 
                g_mutex_lock(&ms_node->parent_streamer->mutex_lock);
 
@@ -937,20 +930,18 @@ static void __ms_rtpbin_pad_added_cb(GstElement * src, GstPad * new_pad, gpointe
                        GstPad *source_pad = gst_element_get_static_pad(ms_node->gst_element, source_pad_name);
                        gst_ghost_pad_set_target(GST_GHOST_PAD(source_pad), new_pad);
 
-                       if (__ms_sink_bin_prepare(ms_node, sink_bin, source_pad)) {
-
-                               if (__ms_bin_add_element(ms_node->parent_streamer->pipeline, sink_bin, TRUE)) {
-                                       gst_element_sync_state_with_parent(sink_bin);
+                       if (__ms_sink_bin_prepare(ms_node, sink_bin, source_pad) &&
+                                               __ms_bin_add_element(ms_node->parent_streamer->pipeline, sink_bin, TRUE)) {
+                               gst_element_sync_state_with_parent(sink_bin);
 
-                                       if (gst_element_link_pads(ms_node->gst_element, source_pad_name, sink_bin, "sink")) {
-                                               __ms_element_set_state(ms_node->gst_element, GST_STATE_PLAYING);
-                                               __ms_generate_dots(ms_node->parent_streamer->pipeline, "playing");
-                                       } else {
-                                               ms_error("Failed to link [rtp_containeer].[%s] and [sink_bin].[sink]\n", source_pad_name);
-                                       }
+                               if (gst_element_link_pads(ms_node->gst_element, source_pad_name, sink_bin, "sink")) {
+                                       __ms_element_set_state(ms_node->gst_element, GST_STATE_PLAYING);
+                                       __ms_generate_dots(ms_node->parent_streamer->pipeline, "rtpbin_playing");
+                               } else {
+                                       ms_error("Failed to link [rtp_containeer].[%s] and [sink_bin].[sink]", source_pad_name);
                                }
                        } else {
-                               ms_error("Failed to prepare sink_bin for pad type [%s]\n", src_pad_type);
+                               ms_error("Failed to prepare sink_bin for pad type [%s]", src_pad_type);
                        }
 
                        MS_SAFE_UNREF(source_pad);
@@ -958,14 +949,9 @@ static void __ms_rtpbin_pad_added_cb(GstElement * src, GstPad * new_pad, gpointe
                }
                g_mutex_unlock(&ms_node->parent_streamer->mutex_lock);
 
-       } else {
-               ms_debug("Node doesn`t have parent streamer or caps media type\n");
+               gst_caps_unref(src_pad_caps);
+               MS_SAFE_UNREF(target_pad);
        }
-
-       gst_caps_unref(src_pad_caps);
-       MS_SAFE_UNREF(target_pad);
-       MS_SAFE_GFREE(new_pad_name);
-       MS_SAFE_GFREE(src_element_name);
 }
 
 int __ms_element_set_state(GstElement * gst_element, GstState gst_state)
@@ -1165,33 +1151,30 @@ GstElement *__ms_rtp_element_create(media_streamer_node_s * ms_node)
                return NULL;
        }
 
-       g_signal_connect(rtp_elem, "pad-added", G_CALLBACK(__ms_rtpbin_pad_added_cb), ms_node);
-
+       __ms_signal_create(&ms_node->sig_list, rtp_elem, "pad-added", G_CALLBACK(__ms_rtpbin_pad_added_cb), ms_node);
        return rtp_container;
 }
 
 gboolean __ms_get_rtp_elements(media_streamer_node_s * ms_node, GstElement ** rtp_elem, GstElement ** rtcp_elem, const gchar * elem_name, const gchar * direction, gboolean auto_create)
 {
-       gboolean ret = TRUE;
-       gchar *rtp_elem_name = NULL;
-       gchar *rtcp_elem_name = NULL;
-       gchar *plugin_name = NULL;
+       ms_retvm_if(!elem_name || !direction, FALSE, "Empty rtp element name or direction.");
 
        GstElement *rtpbin = gst_bin_get_by_name(GST_BIN(ms_node->gst_element), "rtpbin");
 
-       ms_retvm_if(!elem_name || !direction, FALSE, "Empty rtp element name or direction.");
-
+       gboolean ret = TRUE;
+       gchar *plugin_name = NULL;
        if (MS_ELEMENT_IS_INPUT(direction)) {
                plugin_name = g_strdup(DEFAULT_UDP_SOURCE);
        } else if (MS_ELEMENT_IS_OUTPUT(direction)) {
                plugin_name = g_strdup(DEFAULT_UDP_SINK);
        } else {
-               ms_error("Error: invalid parameter name [%s]", elem_name);
+               ms_error("Error: invalid RTP pad direction [%s]", direction);
+               MS_SAFE_UNREF(rtpbin);
                return FALSE;
        }
 
-       rtp_elem_name = g_strdup_printf("%s_%s_rtp", elem_name, direction);
-       rtcp_elem_name = g_strdup_printf("%s_%s_rtcp", elem_name, direction);
+       gchar *rtp_elem_name = g_strdup_printf("%s_%s_rtp", elem_name, direction);
+       gchar *rtcp_elem_name = g_strdup_printf("%s_%s_rtcp", elem_name, direction);
 
        /* Find video udp rtp/rtcp element if it present. */
        *rtp_elem = gst_bin_get_by_name(GST_BIN(ms_node->gst_element), rtp_elem_name);
@@ -1202,9 +1185,12 @@ gboolean __ms_get_rtp_elements(media_streamer_node_s * ms_node, GstElement ** rt
                *rtp_elem = __ms_element_create(plugin_name, rtp_elem_name);
                *rtcp_elem = __ms_element_create(plugin_name, rtcp_elem_name);
                gst_bin_add_many(GST_BIN(ms_node->gst_element), *rtp_elem, *rtcp_elem, NULL);
+               gst_object_ref(*rtp_elem);
+               gst_object_ref(*rtcp_elem);
        } else {
 
                /*rtp/rtcp elements already into rtp bin. */
+               MS_SAFE_UNREF(rtpbin);
                MS_SAFE_GFREE(rtp_elem_name);
                MS_SAFE_GFREE(rtcp_elem_name);
                MS_SAFE_GFREE(plugin_name);
@@ -1236,10 +1222,14 @@ gboolean __ms_get_rtp_elements(media_streamer_node_s * ms_node, GstElement ** rt
 
        if (!ret) {
                ms_error("Can not link [rtpbin] pad to [%s] pad", rtp_elem_name);
+               MS_SAFE_UNREF(*rtp_elem);
+               MS_SAFE_UNREF(*rtcp_elem);
                ret = FALSE;
+               __ms_generate_dots(ms_node->gst_element, "rtp_fail");
        }
 
        __ms_generate_dots(ms_node->gst_element, "rtp");
+       MS_SAFE_UNREF(rtpbin);
        MS_SAFE_GFREE(rtp_elem_name);
        MS_SAFE_GFREE(rtcp_elem_name);
        MS_SAFE_GFREE(plugin_name);
@@ -1358,7 +1348,7 @@ static gboolean __ms_bus_cb(GstBus * bus, GstMessage * message, gpointer userdat
 
                                        gst_message_parse_state_changed(message, &state_old, &state_new, &state_pending);
                                        state_transition_name = g_strdup_printf("%s_%s", gst_element_state_get_name(state_old), gst_element_state_get_name(state_new));
-                                       ms_info("GST_MESSAGE_STATE_CHANGED: [%s] %s", gst_object_get_name(GST_MESSAGE_SRC(message)), state_transition_name);
+                                       ms_info("GST_MESSAGE_STATE_CHANGED: [%s] %s", GST_OBJECT_NAME(GST_MESSAGE_SRC(message)), state_transition_name);
                                        __ms_generate_dots(ms_streamer->pipeline, state_transition_name);
 
                                        MS_SAFE_GFREE(state_transition_name);
@@ -1401,7 +1391,12 @@ int __ms_pipeline_create(media_streamer_s * ms_streamer)
 {
        ms_retvm_if(ms_streamer == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Handle is NULL");
 
-       gst_init(NULL, NULL);
+       GError *err = NULL;
+       if (!gst_init_check(NULL, NULL, &err)) {
+               ms_error("Error: Failed to initialize GStreamer [%s].", err->message);
+               g_clear_error(&err);
+               return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+       }
 
        ms_streamer->pipeline = gst_pipeline_new(MEDIA_STREAMER_PIPELINE_NAME);
        ms_retvm_if(ms_streamer->pipeline == NULL, MEDIA_STREAMER_ERROR_INVALID_OPERATION, "Error creating pipeline");
@@ -1603,42 +1598,37 @@ int __ms_element_set_fmt(media_streamer_node_s * node, const char *pad_name, med
        GValue value = G_VALUE_INIT;
 
        if (node->type == MEDIA_STREAMER_NODE_TYPE_RTP) {
-               /* It is needed to set 'application/x-rtp' for audio and video udpsrc */
+               /* Check if it is a valid pad */
+               GstPad *pad = gst_element_get_static_pad(node->gst_element, pad_name);
+               ms_retvm_if(!pad, MEDIA_STREAMER_ERROR_INVALID_PARAMETER,
+                                               "Error: Failed set format to pad [%s].[%s].", node->name, pad_name);
+               MS_SAFE_UNREF(pad);
+
+               /* It is needed to set 'application/x-rtp' for audio and video udpsrc*/
                media_format_mimetype_e mime;
                int audio_channels, audio_samplerate;
                GstElement *rtp_elem, *rtcp_elem;
                gchar *rtp_caps_str = NULL;
 
-               /*Check if it is a valid pad */
-               GstPad *pad = gst_element_get_static_pad(node->gst_element, pad_name);
-               if (!pad) {
-                       ms_error("Error: Failed set format to pad [%s].[%s].", node->name, pad_name);
-                       return MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
-               }
-
                if (MEDIA_FORMAT_ERROR_NONE == media_format_get_video_info(fmt, &mime, NULL, NULL, NULL, NULL)) {
+                       rtp_caps_str = g_strdup_printf("application/x-rtp,media=video,clock-rate=90000,encoding-name=%s",
+                                               __ms_convert_mime_to_rtp_format(mime));
                        __ms_get_rtp_elements(node, &rtp_elem, &rtcp_elem, "video", "in", FALSE);
 
-                       rtp_caps_str = g_strdup_printf("application/x-rtp,media=video,clock-rate=90000,encoding-name=%s", __ms_convert_mime_to_rtp_format(mime));
-                       caps = gst_caps_from_string(rtp_caps_str);
-                       ms_retvm_if(caps == NULL, MEDIA_STREAMER_ERROR_INVALID_OPERATION, "Fail creating caps from fmt.");
-
-                       obj = __ms_get_property_owner(rtp_elem, "caps", &value);
                } else if (MEDIA_FORMAT_ERROR_NONE == media_format_get_audio_info(fmt, &mime, &audio_channels, &audio_samplerate, NULL, NULL)) {
+                       rtp_caps_str = g_strdup_printf("application/x-rtp,media=audio,clock-rate=%d,encoding-name=%s,channels=%d,payload=96",
+                                               audio_samplerate, __ms_convert_mime_to_rtp_format(mime), audio_channels);
                        __ms_get_rtp_elements(node, &rtp_elem, &rtcp_elem, "audio", "in", FALSE);
-
-                       rtp_caps_str = g_strdup_printf("application/x-rtp,media=audio,clock-rate=%d,encoding-name=%s,channels=%d,payload=96", audio_samplerate, __ms_convert_mime_to_rtp_format(mime), audio_channels);
-                       caps = gst_caps_from_string(rtp_caps_str);
-                       ms_retvm_if(caps == NULL, MEDIA_STREAMER_ERROR_INVALID_OPERATION, "Fail creating caps from fmt.");
-
-                       obj = __ms_get_property_owner(rtp_elem, "caps", &value);
                } else {
                        ms_error("Failed getting media info from fmt.");
                        return MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
                }
+               caps = gst_caps_from_string(rtp_caps_str);
+               obj = __ms_get_property_owner(rtp_elem, "caps", &value);
 
+               MS_SAFE_UNREF(rtp_elem);
+               MS_SAFE_UNREF(rtcp_elem);
                MS_SAFE_GFREE(rtp_caps_str);
-               MS_SAFE_UNREF(pad);
        } else {
                caps = __ms_create_caps_from_fmt(fmt);
                ms_retvm_if(caps == NULL, MEDIA_STREAMER_ERROR_INVALID_OPERATION, "Fail creating caps from fmt.");
@@ -1648,6 +1638,7 @@ int __ms_element_set_fmt(media_streamer_node_s * node, const char *pad_name, med
 
        gst_value_set_caps(&value, caps);
        g_object_set_property(obj, "caps", &value);
+       g_value_unset(&value);
        gst_caps_unref(caps);
 
        return MEDIA_STREAMER_ERROR_NONE;
index 27c6145..c13247c 100755 (executable)
@@ -78,12 +78,16 @@ static int __ms_rtp_node_set_property(media_streamer_node_s * ms_node, const cha
                        if (rtp_elem && rtcp_elem) {
                                __ms_element_set_property(rtp_elem, param, param_value);
                                __ms_element_set_property(rtcp_elem, param, param_value);
+                               MS_SAFE_UNREF(rtp_elem);
+                               MS_SAFE_UNREF(rtcp_elem);
                        }
 
                        __ms_get_rtp_elements(ms_node, &rtp_elem, &rtcp_elem, "video", "out", FALSE);
                        if (rtp_elem && rtcp_elem) {
                                __ms_element_set_property(rtp_elem, param, param_value);
                                __ms_element_set_property(rtcp_elem, param, param_value);
+                               MS_SAFE_UNREF(rtp_elem);
+                               MS_SAFE_UNREF(rtcp_elem);
                        }
                } else {
                        ms_error("Error: Unsupported parameter [%s] for rtp node.", param);
@@ -116,6 +120,8 @@ static int __ms_rtp_node_set_property(media_streamer_node_s * ms_node, const cha
                }
 
                g_strfreev(tokens);
+               MS_SAFE_UNREF(rtp_elem);
+               MS_SAFE_UNREF(rtcp_elem);
                return MEDIA_STREAMER_ERROR_NONE;
        } else {
                ms_error("Invalid rtp parameter name.");
@@ -155,8 +161,8 @@ int __ms_node_create(media_streamer_node_s * node, media_format_h in_fmt, media_
                dec_use = iniparser_getboolean(dict, "general:use decodebin", DEFAULT_USE_DECODEBIN);
                if (dec_use) {
                        node->gst_element = __ms_element_create("decodebin", NULL);
-                       g_signal_connect(node->gst_element, "pad-added", G_CALLBACK(__decodebin_newpad_client_cb), (gpointer) node);
-                       g_signal_connect(node->gst_element, "autoplug-select", G_CALLBACK(__ms_decodebin_autoplug_select), NULL);
+                       __ms_signal_create(&node->sig_list, node->gst_element, "pad-added", G_CALLBACK(__decodebin_newpad_client_cb), node);
+                       __ms_signal_create(&node->sig_list, node->gst_element, "autoplug-select", G_CALLBACK(__ms_decodebin_autoplug_select), NULL);
                } else {
                        format_prefix = g_strdup_printf("%s:decoder", __ms_convert_mime_to_string(mime));
                        plugin_name = __ms_ini_get_string(dict, format_prefix, DEFAULT_VIDEO_DECODER);
@@ -296,8 +302,8 @@ int __ms_src_node_create(media_streamer_node_s * node)
                break;
        case MEDIA_STREAMER_NODE_SRC_TYPE_CUSTOM:
                node->gst_element = __ms_element_create(DEFAULT_APP_SOURCE, NULL);
-               g_signal_connect(node->gst_element, "need-data", G_CALLBACK(__ms_src_start_feed_cb), (gpointer) node);
-               g_signal_connect(node->gst_element, "enough-data", G_CALLBACK(__ms_src_stop_feed_cb), (gpointer) node);
+               __ms_signal_create(&node->sig_list, node->gst_element, "need-data", G_CALLBACK(__ms_src_start_feed_cb), node);
+               __ms_signal_create(&node->sig_list, node->gst_element, "enough-data", G_CALLBACK(__ms_src_stop_feed_cb), node);
                break;
        default:
                ms_error("Error: invalid Src node Type [%d]", node->subtype);
@@ -381,8 +387,8 @@ int __ms_sink_node_create(media_streamer_node_s * node)
        case MEDIA_STREAMER_NODE_SINK_TYPE_CUSTOM:
                node->gst_element = __ms_element_create(DEFAULT_APP_SINK, NULL);
                g_object_set(G_OBJECT(node->gst_element), "emit-signals", TRUE, NULL);
-               g_signal_connect(node->gst_element, "new-sample", G_CALLBACK(__ms_sink_new_buffer_cb), (gpointer) node);
-               g_signal_connect(node->gst_element, "eos", G_CALLBACK(sink_eos), (gpointer) node);
+               __ms_signal_create(&node->sig_list, node->gst_element, "new-sample", G_CALLBACK(__ms_sink_new_buffer_cb), node);
+               __ms_signal_create(&node->sig_list, node->gst_element, "eos", G_CALLBACK(sink_eos), node);
                break;
        default:
                ms_error("Error: invalid Sink node Type [%d]", node->subtype);
@@ -402,9 +408,11 @@ int __ms_sink_node_create(media_streamer_node_s * node)
 
 void __ms_node_destroy(media_streamer_node_s * node)
 {
-       char *node_name = NULL;
+       gchar *node_name = g_strdup(node->name);
+
+       /* Disconnects and clean all node signals */
+       g_list_free_full(node->sig_list, __ms_signal_destroy);
 
-       node_name = g_strdup(node->name);
        MS_SAFE_UNREF(node->gst_element);
        MS_SAFE_FREE(node->name);
        MS_SAFE_FREE(node->callbacks_structure);
@@ -466,10 +474,6 @@ static gboolean __ms_src_need_typefind(GstElement * src)
 
 int __ms_pipeline_prepare(media_streamer_s * ms_streamer)
 {
-       GstElement *unlinked_element = NULL;
-       GstPad *unlinked_pad = NULL;
-
-       GstElement *parent;
        GstElement *found_element;
 
        GstCaps *new_pad_caps = NULL;
@@ -479,43 +483,38 @@ int __ms_pipeline_prepare(media_streamer_s * ms_streamer)
        ms_retvm_if(ms_streamer == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Handle is NULL");
 
        /* Find unlinked element in src_bin */
-       unlinked_pad = gst_bin_find_unlinked_pad(GST_BIN(ms_streamer->src_bin), GST_PAD_SRC);
+       GstPad *unlinked_pad = gst_bin_find_unlinked_pad(GST_BIN(ms_streamer->src_bin), GST_PAD_SRC);
+       GstElement *unlinked_element = NULL;
 
        while (unlinked_pad) {
                unlinked_element = gst_pad_get_parent_element(unlinked_pad);
                ms_debug("Autoplug: found unlinked element [%s]", GST_ELEMENT_NAME(unlinked_element));
 
-               parent = (GstElement *) gst_element_get_parent(GST_OBJECT_CAST(unlinked_element));
-               ms_info("Received new pad '%s' from [%s]", GST_PAD_NAME(unlinked_pad), GST_ELEMENT_NAME(unlinked_element));
-
                /* If element in src bin is filesrc */
                if (__ms_src_need_typefind(unlinked_element)) {
                        found_element = __ms_element_create("decodebin", NULL);
-                       gst_bin_add_many((GstBin *) ms_streamer->topology_bin, found_element, NULL);
-
+                       __ms_bin_add_element(ms_streamer->topology_bin, found_element, FALSE);
                        gst_element_sync_state_with_parent(found_element);
 
-                       if (__ms_bin_find_element_by_klass(ms_streamer->topology_bin, found_element, MEDIA_STREAMER_BIN_KLASS, "rtp_container"))
+                       if (__ms_bin_find_element_by_klass(ms_streamer->topology_bin, found_element, MEDIA_STREAMER_BIN_KLASS, "rtp_container")) {
+                               __ms_signal_create(&ms_streamer->autoplug_sig_list, found_element, "pad-added", G_CALLBACK(__decodebin_newpad_streamer_cb), ms_streamer);
                                g_signal_connect(found_element, "pad-added", G_CALLBACK(__decodebin_newpad_streamer_cb), ms_streamer);
-                       else
+                       } else {
+                               __ms_signal_create(&ms_streamer->autoplug_sig_list, found_element, "pad-added", G_CALLBACK(__decodebin_newpad_cb), ms_streamer);
                                g_signal_connect(found_element, "pad-added", G_CALLBACK(__decodebin_newpad_cb), ms_streamer);
-
-                       g_signal_connect(found_element, "autoplug-select", G_CALLBACK(__ms_decodebin_autoplug_select), NULL);
+                       }
+                       __ms_signal_create(&ms_streamer->autoplug_sig_list, found_element, "autoplug-select", G_CALLBACK(__ms_decodebin_autoplug_select), NULL);
 
                        found_element = __ms_link_with_new_element(unlinked_element, found_element, NULL);
                        __ms_generate_dots(ms_streamer->pipeline, GST_ELEMENT_NAME(found_element));
 
-                       MS_SAFE_UNREF(unlinked_pad);
-
                } else {
 
                        found_element = __ms_element_create(DEFAULT_QUEUE, NULL);
-                       gst_bin_add_many((GstBin *) ms_streamer->topology_bin, found_element, NULL);
-
+                       __ms_bin_add_element(ms_streamer->topology_bin, found_element, FALSE);
                        gst_element_sync_state_with_parent(found_element);
 
                        found_element = __ms_link_with_new_element(unlinked_element, found_element, NULL);
-                       __ms_generate_dots(parent, DEFAULT_QUEUE);
 
                        /* Check the new pad's type */
                        new_pad_caps = gst_pad_query_caps(unlinked_pad, 0);
@@ -533,8 +532,11 @@ int __ms_pipeline_prepare(media_streamer_s * ms_streamer)
                                found_element = __ms_combine_next_element(found_element, MEDIA_STREAMER_PAYLOADER_KLASS, NULL, NULL);
                                found_element = __ms_combine_next_element(found_element, MEDIA_STREAMER_BIN_KLASS, "rtp_container", NULL);
                        }
-                       __ms_generate_dots(parent, GST_ELEMENT_NAME(found_element));
+                       __ms_generate_dots(ms_streamer->pipeline, GST_ELEMENT_NAME(found_element));
+                       gst_caps_unref(new_pad_caps);
                }
+               MS_SAFE_UNREF(unlinked_pad);
+               MS_SAFE_UNREF(unlinked_element);
                unlinked_pad = gst_bin_find_unlinked_pad(GST_BIN(ms_streamer->src_bin), GST_PAD_SRC);
        }
 
@@ -589,6 +591,9 @@ int __ms_pipeline_unprepare(media_streamer_s * ms_streamer)
                ms_debug("Got a few errors during unprepare [%s] bin.", GST_ELEMENT_NAME(bin));\
                ret = MEDIA_STREAMER_ERROR_INVALID_OPERATION;\
        }
+       /* Disconnects and clean all autoplug signals */
+       g_list_free_full(ms_streamer->autoplug_sig_list, __ms_signal_destroy);
+       ms_streamer->autoplug_sig_list = NULL;
 
        MS_BIN_UNPREPARE(ms_streamer->src_bin);
        MS_BIN_UNPREPARE(ms_streamer->topology_bin);
index 436be54..801e012 100644 (file)
@@ -134,11 +134,12 @@ int __ms_streamer_destroy(media_streamer_s * ms_streamer)
 
        MS_SAFE_UNREF(ms_streamer->bus);
        MS_SAFE_UNREF(ms_streamer->pipeline);
+       MS_SAFE_UNREF(ms_streamer->sink_video_bin);
+       MS_SAFE_UNREF(ms_streamer->sink_audio_bin);
 
        g_mutex_unlock(&ms_streamer->mutex_lock);
        g_mutex_clear(&ms_streamer->mutex_lock);
        MS_SAFE_FREE(ms_streamer);
 
-       /*  gst_deinit(); */
        return ret;
 }
index f71b195..523fcab 100644 (file)
@@ -14,9 +14,6 @@
  * limitations under the License.
  */
 
-#ifndef __MEDIA_STREAMER_UTIL_C__
-#define __MEDIA_STREAMER_UTIL_C__
-
 #include <glib/gstdio.h>
 
 #include <media_streamer.h>
@@ -117,8 +114,8 @@ void __ms_load_ini_settings(media_streamer_ini_t * ini)
        __ms_destroy_ini_dictionary(dict);
 
        /* general */
-       ms_debug("Media Streamer param [generate_dot] : %d\n", ini->generate_dot);
-       ms_debug("Media Streamer param [use_decodebin] : %d\n", ini->use_decodebin);
+       ms_debug("Media Streamer param [generate_dot] : %d", ini->generate_dot);
+       ms_debug("Media Streamer param [use_decodebin] : %d", ini->use_decodebin);
 }
 
 static void __ms_check_ini_status(void)
@@ -226,4 +223,40 @@ media_format_mimetype_e __ms_convert_string_format_to_mime(const char *format_ty
        }
 }
 
-#endif
+void __ms_signal_create(GList **sig_list, GstElement *obj, const char *sig_name, GCallback cb, gpointer user_data)
+{
+       ms_retm_if(!sig_list || !obj || !sig_name, "Empty signal data!");
+
+       media_streamer_signal_s *sig_data = (media_streamer_signal_s*) g_try_malloc(sizeof(media_streamer_signal_s));
+       if (!sig_data) {
+               ms_error("Failed to create signal [%s] for object [%s]", sig_name, GST_OBJECT_NAME(obj));
+               return;
+       }
+
+       sig_data->obj = G_OBJECT(obj);
+       sig_data->signal_id = g_signal_connect(sig_data->obj, sig_name, cb, user_data);
+
+       if (sig_data->signal_id > 0) {
+               *sig_list = g_list_append(*sig_list, sig_data);
+               ms_debug("Signal [%s] with id[%lu] connected to object [%s].",
+                                               sig_name, sig_data->signal_id, GST_OBJECT_NAME(sig_data->obj));
+       } else {
+               ms_error("Failed to connect signal [%s] for object [%s]", sig_name, GST_OBJECT_NAME(obj));
+       }
+}
+
+void __ms_signal_destroy(void *data)
+{
+       media_streamer_signal_s *sig_data = (media_streamer_signal_s *) data;
+       ms_retm_if(!sig_data, "Empty signal data!");
+
+       if (sig_data->obj && GST_IS_ELEMENT(sig_data->obj)) {
+               if (g_signal_handler_is_connected(sig_data->obj, sig_data->signal_id)) {
+                       g_signal_handler_disconnect(sig_data->obj, sig_data->signal_id);
+                       ms_debug("Signal with id[%lu] disconnected from object [%s].",
+                                               sig_data->signal_id, GST_OBJECT_NAME(sig_data->obj));
+               }
+       }
+
+       MS_SAFE_GFREE(sig_data);
+}
index 1dc45b9..fa83f23 100755 (executable)
@@ -14,7 +14,6 @@
  * limitations under the License.
  */
 
-#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
@@ -80,6 +79,7 @@ typedef enum {
 #define DEFAULT_IP_ADDR   "127.0.0.1"
 #define DEFAULT_SEEK_POS   0
 #define MSEC_MULTIPLIER   1000
+#define MAX_NODES_COUNT   50
 
 #define VIDEO_PORT 5000
 #define AUDIO_PORT 6000
@@ -92,6 +92,10 @@ static media_streamer_h g_media_streamer;
 static media_streamer_h g_media_streamer_2;
 static media_streamer_h current_media_streamer = &g_media_streamer;
 
+media_streamer_node_h g_nodes[MAX_NODES_COUNT] = {0,};
+int g_node_counter = 0;
+#define APPEND_NODE(x) {g_nodes[g_node_counter++] = x; }
+
 GMainLoop *g_loop;
 
 gchar *g_broadcast_address = NULL;
@@ -337,16 +341,19 @@ static void _create_file_playing()
        media_streamer_node_create_src(MEDIA_STREAMER_NODE_SRC_TYPE_FILE, &file_src);
        media_streamer_node_set_param(file_src, MEDIA_STREAMER_PARAM_URI, g_uri);
        media_streamer_node_add(current_media_streamer, file_src);
+       APPEND_NODE(file_src);
 
        /*********************** videosink *********************************** */
        media_streamer_node_h video_sink = NULL;
        media_streamer_node_create_sink(MEDIA_STREAMER_NODE_SINK_TYPE_SCREEN, &video_sink);
        media_streamer_node_add(current_media_streamer, video_sink);
+       APPEND_NODE(video_sink);
 
        /*********************** audiosink *********************************** */
        media_streamer_node_h audio_sink = NULL;
        media_streamer_node_create_sink(MEDIA_STREAMER_NODE_SINK_TYPE_AUDIO, &audio_sink);
        media_streamer_node_add(current_media_streamer, audio_sink);
+       APPEND_NODE(audio_sink);
 }
 
 static void _create_file_sub_playing()
@@ -355,21 +362,25 @@ static void _create_file_sub_playing()
        media_streamer_node_create_src(MEDIA_STREAMER_NODE_SRC_TYPE_FILE, &file_sub_src);
        media_streamer_node_set_param(file_sub_src, MEDIA_STREAMER_PARAM_URI, g_uri);
        media_streamer_node_add(current_media_streamer, file_sub_src);
+       APPEND_NODE(file_sub_src);
 
        media_streamer_node_h txt_src = NULL;
        media_streamer_node_create_src(MEDIA_STREAMER_NODE_SRC_TYPE_FILE, &txt_src);
        media_streamer_node_set_param(txt_src, MEDIA_STREAMER_PARAM_URI, g_sub_uri);
        media_streamer_node_add(current_media_streamer, txt_src);
+       APPEND_NODE(txt_src);
 
        /*********************** videosink *********************************** */
        media_streamer_node_h video_sink = NULL;
        media_streamer_node_create_sink(MEDIA_STREAMER_NODE_SINK_TYPE_SCREEN, &video_sink);
        media_streamer_node_add(current_media_streamer, video_sink);
+       APPEND_NODE(video_sink);
 
        /*********************** audiosink *********************************** */
        media_streamer_node_h audio_sink = NULL;
        media_streamer_node_create_sink(MEDIA_STREAMER_NODE_SINK_TYPE_AUDIO, &audio_sink);
        media_streamer_node_add(current_media_streamer, audio_sink);
+       APPEND_NODE(audio_sink);
 }
 
 static void _create_file_streaming()
@@ -379,6 +390,7 @@ static void _create_file_streaming()
        media_streamer_node_create_src(MEDIA_STREAMER_NODE_SRC_TYPE_FILE, &file_src);
        media_streamer_node_set_param(file_src, MEDIA_STREAMER_PARAM_URI, g_uri);
        media_streamer_node_add(current_media_streamer, file_src);
+       APPEND_NODE(file_src);
 }
 
 static void _create_http_playing()
@@ -387,16 +399,19 @@ static void _create_http_playing()
        media_streamer_node_create_src(MEDIA_STREAMER_NODE_SRC_TYPE_HTTP, &http_src);
        media_streamer_node_set_param(http_src, MEDIA_STREAMER_PARAM_URI, g_uri);
        media_streamer_node_add(current_media_streamer, http_src);
+       APPEND_NODE(http_src);
 
        /*********************** videosink *********************************** */
        media_streamer_node_h video_sink = NULL;
        media_streamer_node_create_sink(MEDIA_STREAMER_NODE_SINK_TYPE_SCREEN, &video_sink);
        media_streamer_node_add(current_media_streamer, video_sink);
+       APPEND_NODE(video_sink);
 
        /*********************** audiosink *********************************** */
        media_streamer_node_h audio_sink = NULL;
        media_streamer_node_create_sink(MEDIA_STREAMER_NODE_SINK_TYPE_AUDIO, &audio_sink);
        media_streamer_node_add(current_media_streamer, audio_sink);
+       APPEND_NODE(audio_sink);
 }
 
 static void _create_rtp_streamer(media_streamer_node_h rtp_bin)
@@ -416,16 +431,19 @@ static void _create_rtp_streamer(media_streamer_node_h rtp_bin)
                }
 
                media_streamer_node_add(current_media_streamer, video_src);
+               APPEND_NODE(video_src);
 
                /*********************** encoder **************************************** */
                media_streamer_node_h video_enc = NULL;
                media_streamer_node_create(MEDIA_STREAMER_NODE_TYPE_VIDEO_ENCODER, NULL, vfmt_encoded, &video_enc);
                media_streamer_node_add(current_media_streamer, video_enc);
+               APPEND_NODE(video_enc);
 
                /*********************** videopay *************************************** */
                media_streamer_node_h video_pay = NULL;
                media_streamer_node_create(MEDIA_STREAMER_NODE_TYPE_VIDEO_PAY, NULL, vfmt_encoded, &video_pay);
                media_streamer_node_add(current_media_streamer, video_pay);
+               APPEND_NODE(video_pay);
 
                /*====================Linking Video Streamer=========================== */
                media_streamer_node_link(video_src, "src", video_enc, "sink");
@@ -449,16 +467,19 @@ static void _create_rtp_streamer(media_streamer_node_h rtp_bin)
                }
 
                media_streamer_node_add(current_media_streamer, audio_src);
+               APPEND_NODE(audio_src);
 
                /*********************** audioencoder *********************************** */
                media_streamer_node_h audio_enc = NULL;
                media_streamer_node_create(MEDIA_STREAMER_NODE_TYPE_AUDIO_ENCODER, NULL, NULL, &audio_enc);
                media_streamer_node_add(current_media_streamer, audio_enc);
+               APPEND_NODE(audio_enc);
 
                /*********************** rtpL16pay *********************************** */
                media_streamer_node_h audio_pay = NULL;
                media_streamer_node_create(MEDIA_STREAMER_NODE_TYPE_AUDIO_PAY, NULL, NULL, &audio_pay);
                media_streamer_node_add(current_media_streamer, audio_pay);
+               APPEND_NODE(audio_pay);
 
                /*====================Linking Audio Streamer========================== */
                media_streamer_node_link(audio_src, "src", audio_enc, "sink");
@@ -487,6 +508,7 @@ static void _create_rtp_streamer_autoplug(media_streamer_node_h rtp_bin)
                }
 
                media_streamer_node_add(current_media_streamer, video_src);
+               APPEND_NODE(video_src);
 
                g_print("== success streamer_autoplug video part \n");
        }
@@ -504,6 +526,7 @@ static void _create_rtp_streamer_autoplug(media_streamer_node_h rtp_bin)
                }
 
                media_streamer_node_add(current_media_streamer, audio_src);
+               APPEND_NODE(audio_src);
 
                g_print("== success streamer_autoplug audio part \n");
        }
@@ -519,21 +542,25 @@ static void _create_rtp_client(media_streamer_node_h rtp_bin)
                media_streamer_node_h video_depay = NULL;
                media_streamer_node_create(MEDIA_STREAMER_NODE_TYPE_VIDEO_DEPAY, NULL, vfmt_encoded, &video_depay);
                media_streamer_node_add(current_media_streamer, video_depay);
+               APPEND_NODE(video_depay);
 
                /*********************** videodec *********************************** */
                media_streamer_node_h video_dec = NULL;
                media_streamer_node_create(MEDIA_STREAMER_NODE_TYPE_VIDEO_DECODER, NULL, vfmt_encoded, &video_dec);
                media_streamer_node_add(current_media_streamer, video_dec);
+               APPEND_NODE(video_dec);
 
                /*********************** videoconvertor *********************************** */
                media_streamer_node_h video_conv = NULL;
                media_streamer_node_create(MEDIA_STREAMER_NODE_TYPE_VIDEO_CONVERTER, NULL, vfmt_encoded, &video_conv);
                media_streamer_node_add(current_media_streamer, video_conv);
+               APPEND_NODE(video_conv);
 
                /*********************** videosink *********************************** */
                media_streamer_node_h video_sink = NULL;
                media_streamer_node_create_sink(MEDIA_STREAMER_NODE_SINK_TYPE_SCREEN, &video_sink);
                media_streamer_node_add(current_media_streamer, video_sink);
+               APPEND_NODE(video_sink);
 
                /*====================Linking Video Client=========================== */
                media_streamer_node_link(video_depay, "src", video_dec, "sink");
@@ -549,21 +576,25 @@ static void _create_rtp_client(media_streamer_node_h rtp_bin)
                media_streamer_node_h audio_depay = NULL;
                media_streamer_node_create(MEDIA_STREAMER_NODE_TYPE_AUDIO_DEPAY, NULL, NULL, &audio_depay);
                media_streamer_node_add(current_media_streamer, audio_depay);
+               APPEND_NODE(audio_depay);
 
                /*********************** audiodecoder *********************************** */
                media_streamer_node_h audio_dec = NULL;
                media_streamer_node_create(MEDIA_STREAMER_NODE_TYPE_AUDIO_DECODER, NULL, NULL, &audio_dec);
                media_streamer_node_add(current_media_streamer, audio_dec);
+               APPEND_NODE(audio_dec);
 
                /*********************** audioconverter *********************************** */
                media_streamer_node_h audio_conv = NULL;
                media_streamer_node_create(MEDIA_STREAMER_NODE_TYPE_AUDIO_CONVERTER, NULL, NULL, &audio_conv);
                media_streamer_node_add(current_media_streamer, audio_conv);
+               APPEND_NODE(audio_conv);
 
                /*********************** audiosink *********************************** */
                media_streamer_node_h audio_sink = NULL;
                media_streamer_node_create_sink(MEDIA_STREAMER_NODE_SINK_TYPE_AUDIO, &audio_sink);
                media_streamer_node_add(current_media_streamer, audio_sink);
+               APPEND_NODE(audio_sink);
 
                /*====================Linking Audio Client=========================== */
                media_streamer_node_link(audio_depay, "src", audio_dec, "sink");
@@ -585,6 +616,7 @@ static void _create_rtp_client_autoplug(media_streamer_node_h rtp_bin)
                media_streamer_node_h video_sink = NULL;
                media_streamer_node_create_sink(MEDIA_STREAMER_NODE_SINK_TYPE_SCREEN, &video_sink);
                media_streamer_node_add(current_media_streamer, video_sink);
+               APPEND_NODE(video_sink);
 
                g_print("== success client_autoplug video part \n");
        }
@@ -595,6 +627,7 @@ static void _create_rtp_client_autoplug(media_streamer_node_h rtp_bin)
                media_streamer_node_h audio_sink = NULL;
                media_streamer_node_create_sink(MEDIA_STREAMER_NODE_SINK_TYPE_AUDIO, &audio_sink);
                media_streamer_node_add(current_media_streamer, audio_sink);
+               APPEND_NODE(audio_sink);
 
                g_print("== success client_autoplug audio part \n");
        }
@@ -610,6 +643,7 @@ static media_streamer_node_h _create_rtp(int video_port,
        media_streamer_node_create(MEDIA_STREAMER_NODE_TYPE_RTP, NULL, NULL, &rtp_bin);
        set_rtp_params(rtp_bin, g_broadcast_address, video_port, audio_port, second_client);
        media_streamer_node_add(current_media_streamer, rtp_bin);
+       APPEND_NODE(rtp_bin);
        return rtp_bin;
 }
 
@@ -666,12 +700,14 @@ static void _create_app_test()
        media_streamer_node_h app_src = NULL;
        media_streamer_node_create_src(MEDIA_STREAMER_NODE_SRC_TYPE_CUSTOM, &app_src);
        media_streamer_node_add(current_media_streamer, app_src);
+       APPEND_NODE(app_src);
 
        /*********************** app_sink *********************************** */
        media_streamer_node_h app_sink = NULL;
        media_streamer_node_create_sink(MEDIA_STREAMER_NODE_SINK_TYPE_CUSTOM, &app_sink);
        media_streamer_node_set_pad_format(app_sink, "sink", vfmt_raw);
        media_streamer_node_add(current_media_streamer, app_sink);
+       APPEND_NODE(app_sink);
 
        /*====================Linking ======================================== */
        media_streamer_node_link(app_src, "src", app_sink, "sink");
@@ -722,6 +758,14 @@ void reset_current_menu_state(void)
                g_free(g_sub_uri);
                g_sub_uri = NULL;
        }
+
+       /* Clean Up Nodes */
+       int i = g_node_counter-1;
+       for (; i >= 0; --i) {
+               media_streamer_node_destroy(g_nodes[i]);
+               g_nodes[i] = NULL;
+       }
+       g_node_counter = 0;
 }
 
 void quit()
@@ -944,17 +988,26 @@ static void run_preset(void)
                        _create_rtp_client_autoplug(rtp_bin);
                else
                        _create_rtp_client(rtp_bin);
-
                break;
        case PRESET_VOIP:
                rtp_bin = _create_rtp(VIDEO_PORT, AUDIO_PORT, FALSE);
-               _create_rtp_streamer(rtp_bin);
-               _create_rtp_client(rtp_bin);
+               if (g_autoplug_mode) {
+                       _create_rtp_streamer_autoplug(rtp_bin);
+                       _create_rtp_client_autoplug(rtp_bin);
+               } else {
+                       _create_rtp_streamer(rtp_bin);
+                       _create_rtp_client(rtp_bin);
+               }
                break;
        case PRESET_VOIP_2:
                rtp_bin = _create_rtp(VIDEO_PORT, AUDIO_PORT, TRUE);
-               _create_rtp_streamer(rtp_bin);
-               _create_rtp_client(rtp_bin);
+               if (g_autoplug_mode) {
+                       _create_rtp_streamer_autoplug(rtp_bin);
+                       _create_rtp_client_autoplug(rtp_bin);
+               } else {
+                       _create_rtp_streamer(rtp_bin);
+                       _create_rtp_client(rtp_bin);
+               }
                break;
        case PRESET_DOUBLE_VOIP_SERVER:
                rtp_bin = _create_rtp(VIDEO_PORT, AUDIO_PORT, FALSE);
@@ -1397,5 +1450,8 @@ int main(int argc, char **argv)
 
        g_loop = g_main_loop_new(NULL, FALSE);
        g_main_loop_run(g_loop);
+
+       g_main_loop_unref(g_loop);
+       g_io_channel_unref(stdin_channel);
        return 0;
 }