Added File Streaming scenario. Bug fixes. 15/48615/2 accepted/tizen/mobile/20151002.094530 accepted/tizen/tv/20151002.094539 accepted/tizen/wearable/20151002.094545 submit/tizen/20151002.091947
authorVyacheslav Valkovoy <v.valkovoy@samsung.com>
Wed, 23 Sep 2015 20:54:09 +0000 (23:54 +0300)
committerVyacheslav Valkovoy <v.valkovoy@samsung.com>
Wed, 23 Sep 2015 21:03:50 +0000 (00:03 +0300)
Change-Id: If64b2745f650018eefcb0107baa0cc2f2b05487d

include/media_streamer_gst.h
include/media_streamer_node.h
include/media_streamer_util.h
packaging/capi-media-streamer.spec
src/media_streamer_gst.c
src/media_streamer_node.c
test/media_streamer_test.c

index 5fbeef5..fb253cc 100755 (executable)
 #define MEDIA_STREAMER_AUDIO_SINK_BIN_NAME "streamer_audio_sink"
 #define MEDIA_STREAMER_TOPOLOGY_BIN_NAME "streamer_topology"
 
+#define MEDIA_STREAMER_PAYLOADER_KLASS "Codec/Payloader/Network/RTP"
+#define MEDIA_STREAMER_RTP_KLASS "Filter/Network/RTP"
 #define MEDIA_STREAMER_DEPAYLOADER_KLASS "Depayloader/Network/RTP"
-#define MEDIA_STREAMER_DECODEBIN_KLASS "Generic/Bin"
-#define MEDIA_STREAMER_PARSER_KLASS "Parser/Converter"
+#define MEDIA_STREAMER_BIN_KLASS "Generic/Bin"
+#define MEDIA_STREAMER_PARSER_KLASS "Codec/Parser/Converter"
+#define MEDIA_STREAMER_CONVERTER_KLASS "Filter/Converter"
 #define MEDIA_STREAMER_DECODER_KLASS "Codec/Decoder"
 #define MEDIA_STREAMER_SINK_KLASS "Sink"
 
 void __ms_generate_dots(GstElement *bin, gchar *name_tag);
 
 /**
+ * @brief Creates GstElement by klass name.
+ *
+ * @since_tizen 3.0
+ */
+GstElement *__ms_create_element_by_registry(GstPad *src_pad, const gchar *klass_name);
+
+/**
+ * @brief Links two Gstelements and returns the last one.
+ *
+ * @since_tizen 3.0
+ */
+GstElement * __ms_link_with_new_element(GstElement *previous_element,
+                                        GstElement *new_element,
+                                        const gchar *next_elem_bin_name);
+
+/**
  * @brief Creates GstElement by plugin name.
  *
  * @since_tizen 3.0
@@ -110,13 +129,31 @@ gboolean __ms_element_set_property(GstElement *src_element,
 gboolean __ms_element_unlink(GstElement *src_element);
 
 /**
- * @brief Callback function to link decodebin with the sink element.
+ * @brief Callback function to link decodebin with the sink element at the streamer part.
+ *
+ * @since_tizen 3.0
+ */
+void __decodebin_newpad_streamer_cb(GstElement *decodebin, GstPad *pad, gpointer user_data);
+
+/**
+ * @brief Callback function to link decodebin with the sink element at the client part.
  *
  * @since_tizen 3.0
  */
 void __decodebin_newpad_cb(GstElement *decodebin, GstPad *pad, gpointer user_data);
 
 /**
+ * @brief Creates next element by klass or by properties and links with the previous one.
+ *
+ * @since_tizen 3.0
+ */
+GstElement * __ms_combine_next_element(GstElement *previous_element,
+                                       const gchar *next_elem_klass_name,
+                                       const gchar *next_elem_bin_name,
+                                       const gchar *element_type,
+                                       gchar *default_element);
+
+/**
  * @brief Creates pipeline, bus and src/sink/topology bins.
  *
  * @since_tizen 3.0
index e40cf2f..afb522f 100755 (executable)
 #include <media_streamer_priv.h>
 
 /**
+ * @brief Sets property to media streamer node with key and value.
+ *
+ * @since_tizen 3.0
+ */
+int __ms_node_set_property(media_streamer_node_s *ms_node,
+                                  const gchar *param_key,
+                                  const gchar *param_value);
+
+/**
  * @brief Creates media streamer node using input and output format.
  *
  * @since_tizen 3.0
index 066c409..e1ffa30 100755 (executable)
@@ -76,7 +76,6 @@ extern "C" {
                } \
        } while(0)
 
-
 #define MS_SAFE_FREE(src)           {if(src) {free(src); src = NULL;}}
 #define MS_SAFE_GFREE(src)          {if(src) {g_free(src); src = NULL;}}
 #define MS_SAFE_UNREF(src)          {if(src) {gst_object_unref(GST_OBJECT(src)); src = NULL;}}
@@ -98,6 +97,8 @@ typedef struct __media_streamer_ini {
 
 } media_streamer_ini_t;
 
+#define COMPARED_NUMBER                        5
+
 /*Test elements*/
 #define DEFAULT_VIDEO_TEST_SOURCE           "videotestsrc"
 #define DEFAULT_AUDIO_TEST_SOURCE           "audiotestsrc"
@@ -132,6 +133,7 @@ typedef struct __media_streamer_ini {
 #define DEFAULT_VIDEO_RTPDEPAY              "rtph263depay"
 
 /* audio format defaults */
+#define DEFAULT_AUDIO_PARSER                "aacparse"
 #define DEFAULT_AUDIO_RTPPAY                "rtpL16pay"
 #define DEFAULT_AUDIO_RTPDEPAY              "rtpL16depay"
 
@@ -143,6 +145,8 @@ typedef struct __media_streamer_ini {
 #define MS_ELEMENT_IS_INPUT(el) g_strrstr(el, "in")
 #define MS_ELEMENT_IS_AUDIO(el) g_strrstr(el, "audio")
 #define MS_ELEMENT_IS_VIDEO(el) g_strrstr(el, "video")
+#define MS_ELEMENT_IS_ENCODER(el) g_strrstr(el, "encoder")
+#define MS_ELEMENT_IS_DECODER(el) g_strrstr(el, "decoder")
 
 #define MEDIA_STREAMER_DEFAULT_DOT_DIR "/tmp"
 #define MEDIA_STREAMER_DEFAULT_INI \
index 020d2a0..7251a8a 100755 (executable)
@@ -1,6 +1,6 @@
 Name:       capi-media-streamer
 Summary:    A Media Streamer library in Tizen Native API
-Version:    0.1.2
+Version:    0.1.3
 Release:    0
 Group:      Multimedia/API
 License:    Apache-2.0
index dc459cf..511b2f7 100755 (executable)
@@ -42,7 +42,8 @@ static int __ms_add_no_target_ghostpad(GstElement *gst_bin,
        gchar *bin_name = gst_element_get_name(gst_bin);
        GstPad *ghost_pad = gst_ghost_pad_new_no_target(ghost_pad_name, pad_direction);
        if (gst_element_add_pad(GST_ELEMENT(gst_bin), ghost_pad)) {
-               ms_info("Added [%s] empty ghostpad into [%s]", ghost_pad_name, bin_name);
+       gst_pad_set_active(ghost_pad, TRUE);
+       ms_info("Added [%s] empty ghostpad into [%s]", ghost_pad_name, bin_name);
        } else {
                ms_info("Error: Failed to add empty [%s] ghostpad into [%s]", ghost_pad_name, bin_name);
                ret = MEDIA_STREAMER_ERROR_INVALID_OPERATION;
@@ -111,7 +112,7 @@ static GObject *__ms_get_property_owner(GstElement *element, const gchar *key, G
 
        g_value_init(value, param->value_type);
 
-       if (!param->flags & G_PARAM_WRITABLE) {
+       if (!(param->flags & G_PARAM_WRITABLE)) {
 
                /* Skip properties which user can not change. */
                ms_error("Error: node param [%s] is not writable!", key);
@@ -143,94 +144,94 @@ gboolean __ms_element_set_property(GstElement *element, const char *key, const g
                        return FALSE;
                }
 
-               if (!g_strcmp0(init_name, MEDIA_STREAMER_PARAM_CAMERA_ID)) {
+               if (!g_strcmp0(key, MEDIA_STREAMER_PARAM_CAMERA_ID)) {
                        pint = atoi(param_value);
                        g_value_set_int(&value, pint);
                        g_object_set(obj, init_name, pint, NULL);
                        ms_info("Set int value: [%d]", g_value_get_int(&value));
-               } else if (!g_strcmp0(init_name, MEDIA_STREAMER_PARAM_CAPTURE_WIDTH)) {
+               } else if (!g_strcmp0(key, MEDIA_STREAMER_PARAM_CAPTURE_WIDTH)) {
                        pint = atoi(param_value);
                        g_value_set_int(&value, pint);
                        g_object_set(obj, init_name, pint, NULL);
                        ms_info("Set int value: [%d]", g_value_get_int(&value));
-               } else if (!g_strcmp0(init_name, MEDIA_STREAMER_PARAM_CAPTURE_HEIGHT)) {
+               } else if (!g_strcmp0(key, MEDIA_STREAMER_PARAM_CAPTURE_HEIGHT)) {
                        pint = atoi(param_value);
                        g_value_set_int(&value, pint);
                        g_object_set(obj, init_name, pint, NULL);
                        ms_info("Set int value: [%d]", g_value_get_int(&value));
-               } else if (!g_strcmp0(init_name, MEDIA_STREAMER_PARAM_IS_LIVE_STREAM)) {
+               } else if (!g_strcmp0(key, MEDIA_STREAMER_PARAM_IS_LIVE_STREAM)) {
                        bool_val = !g_strcmp0(param_value, "true") ? TRUE : FALSE;
                        g_value_set_boolean(&value, bool_val);
                        g_object_set(obj, init_name, bool_val, NULL);
                        ms_info("Set boolean value: [%d]", g_value_get_boolean(&value));
-               } else if (!g_strcmp0(init_name, MEDIA_STREAMER_PARAM_URI)) {
+               } else if (!g_strcmp0(key, MEDIA_STREAMER_PARAM_URI)) {
                        g_value_set_string(&value, param_value);
                        g_object_set(obj, init_name, param_value, NULL);
                        ms_info("Set string value: [%s]", g_value_get_string(&value));
-               } else if (!g_strcmp0(init_name, MEDIA_STREAMER_PARAM_USER_AGENT)) {
+               } else if (!g_strcmp0(key, MEDIA_STREAMER_PARAM_USER_AGENT)) {
                        g_value_set_string(&value, param_value);
                        g_object_set(obj, init_name, param_value, NULL);
                        ms_info("Set string value: [%s]", g_value_get_string(&value));
-               } else if (!g_strcmp0(init_name, MEDIA_STREAMER_PARAM_STREAM_TYPE)) {
+               } else if (!g_strcmp0(key, MEDIA_STREAMER_PARAM_STREAM_TYPE)) {
                        pint = atoi(param_value);
                        g_object_set(obj, init_name, pint, NULL);
                        ms_info("Set int value: [%d] ", pint);
-               } else if (!g_strcmp0(init_name, MEDIA_STREAMER_PARAM_PORT)) {
+               } else if (!g_strcmp0(key, MEDIA_STREAMER_PARAM_PORT)) {
                        pint = atoi(param_value);
                        g_value_set_int(&value, pint);
                        g_object_set(obj, init_name, pint, NULL);
                        ms_info("Set int value: [%d]", g_value_get_int(&value));
-               } else if (!g_strcmp0(init_name, MEDIA_STREAMER_PARAM_VIDEO_IN_PORT)) {
+               } else if (!g_strcmp0(key, MEDIA_STREAMER_PARAM_VIDEO_IN_PORT)) {
                        pint = atoi(param_value);
                        g_value_set_int(&value, pint);
                        g_object_set(obj, init_name, pint, NULL);
                        ms_info("Set int value: [%d]", g_value_get_int(&value));
-               } else if (!g_strcmp0(init_name, MEDIA_STREAMER_PARAM_AUDIO_IN_PORT)) {
+               } else if (!g_strcmp0(key, MEDIA_STREAMER_PARAM_AUDIO_IN_PORT)) {
                        pint = atoi(param_value);
                        g_value_set_int(&value, pint);
                        g_object_set(obj, init_name, pint, NULL);
                        ms_info("Set int value: [%d]", g_value_get_int(&value));
-               } else if (!g_strcmp0(init_name, MEDIA_STREAMER_PARAM_VIDEO_OUT_PORT)) {
+               } else if (!g_strcmp0(key, MEDIA_STREAMER_PARAM_VIDEO_OUT_PORT)) {
                        pint = atoi(param_value);
                        g_value_set_int(&value, pint);
                        g_object_set(obj, init_name, pint, NULL);
                        ms_info("Set int value: [%d]", g_value_get_int(&value));
-               } else if (!g_strcmp0(init_name, MEDIA_STREAMER_PARAM_AUDIO_OUT_PORT)) {
+               } else if (!g_strcmp0(key, MEDIA_STREAMER_PARAM_AUDIO_OUT_PORT)) {
                        pint = atoi(param_value);
                        g_value_set_int(&value, pint);
                        g_object_set(obj, init_name, pint, NULL);
                        ms_info("Set int value: [%d]", g_value_get_int(&value));
-               } else if (!g_strcmp0(init_name, MEDIA_STREAMER_PARAM_IP_ADDRESS)) {
+               } else if (!g_strcmp0(key, MEDIA_STREAMER_PARAM_IP_ADDRESS)) {
                        g_value_set_string(&value, param_value);
                        g_object_set(obj, init_name, param_value, NULL);
                        ms_info("Set string value: [%s]", g_value_get_string(&value));
-               } else if (!g_strcmp0(init_name, MEDIA_STREAMER_PARAM_AUDIO_DEVICE)) {
+               } else if (!g_strcmp0(key, MEDIA_STREAMER_PARAM_AUDIO_DEVICE)) {
                        g_value_set_string(&value, param_value);
                        g_object_set(obj, init_name, param_value, NULL);
                        ms_info("Set string value: [%s]", g_value_get_string(&value));
-               } else if (!g_strcmp0(init_name, MEDIA_STREAMER_PARAM_CLOCK_SYNCHRONIZED)) {
+               } else if (!g_strcmp0(key, MEDIA_STREAMER_PARAM_CLOCK_SYNCHRONIZED)) {
                        bool_val = !g_strcmp0(param_value, "true") ? TRUE : FALSE;
                        g_value_set_boolean(&value, bool_val);
                        g_object_set(obj, init_name, bool_val, NULL);
                        ms_info("Set boolean value: [%d]", g_value_get_boolean(&value));
-               } else if (!g_strcmp0(init_name, MEDIA_STREAMER_PARAM_ROTATE)) {
+               } else if (!g_strcmp0(key, MEDIA_STREAMER_PARAM_ROTATE)) {
                        pint = atoi(param_value);
                        g_object_set(obj, init_name, pint, NULL);
                        ms_info("Set int value: [%d] ", pint);
-               } else if (!g_strcmp0(init_name, MEDIA_STREAMER_PARAM_FLIP)) {
+               } else if (!g_strcmp0(key, MEDIA_STREAMER_PARAM_FLIP)) {
                        pint = atoi(param_value);
                        g_object_set(obj, init_name, pint, NULL);
                        ms_info("Set int value: [%d] ", pint);
-               } else if (!g_strcmp0(init_name, MEDIA_STREAMER_PARAM_DISPLAY_GEOMETRY_METHOD)) {
+               } else if (!g_strcmp0(key, MEDIA_STREAMER_PARAM_DISPLAY_GEOMETRY_METHOD)) {
                        pint = atoi(param_value);
                        g_object_set(obj, init_name, pint, NULL);
                        ms_info("Set int value: [%d] ", pint);
-               } else if (!g_strcmp0(init_name, MEDIA_STREAMER_PARAM_VISIBLE)) {
+               } else if (!g_strcmp0(key, MEDIA_STREAMER_PARAM_VISIBLE)) {
                        bool_val = !g_strcmp0(param_value, "true") ? TRUE : FALSE;
                        g_value_set_boolean(&value, bool_val);
                        g_object_set(obj, init_name, bool_val, NULL);
                        ms_info("Set boolean value: [%d]", g_value_get_boolean(&value));
-               } else if (!g_strcmp0(init_name, MEDIA_STREAMER_PARAM_HOST)) {
+               } else if (!g_strcmp0(key, MEDIA_STREAMER_PARAM_HOST)) {
                        g_value_set_string(&value, param_value);
                        g_object_set(obj, init_name, param_value, NULL);
                        ms_info("Set string value: [%s]", g_value_get_string(&value));
@@ -350,23 +351,49 @@ static void __ms_link_elements_on_pad_added_cb(GstPad *new_pad, GstElement *sink
 }
 #endif
 
-static GstElement *__ms_bin_find_element_by_klass(GstElement *sink_bin, const gchar *klass_name)
+static GstElement *__ms_bin_find_element_by_klass(GstElement *sink_bin,
+                                                  const gchar *klass_name,
+                                                  const gchar *bin_name)
 {
        GValue elem = G_VALUE_INIT;
        GstIterator *bin_iterator = gst_bin_iterate_sorted(GST_BIN(sink_bin));
        GstElement *found_element;
        gboolean found = FALSE;
 
-       while (GST_ITERATOR_OK == gst_iterator_next(bin_iterator, &elem)) {
+       gboolean unlinked_pad_found = FALSE;
+
+       GValue element = G_VALUE_INIT;
+       GstPad *pad = NULL;
+       GstIterator *pad_iterator = NULL;
 
-               found_element = (GstElement *)g_value_get_object(&elem);
+       while (GST_ITERATOR_OK == gst_iterator_next(bin_iterator, &elem)) {
+               found_element = (GstElement *) g_value_get_object(&elem);
                const gchar *found_klass = gst_element_factory_get_klass(gst_element_get_factory(found_element));
 
-               if (g_strrstr(found_klass, klass_name)) {
-                       found = TRUE;
-                       break;
-               }
+               if (klass_name && g_strrstr(found_klass, klass_name)) {
+
+                       /* Check if found element has any unlinked sink pad */
+                       pad_iterator = gst_element_iterate_sink_pads(found_element);
+                       while (GST_ITERATOR_OK == gst_iterator_next(pad_iterator, &element)) {
+                               pad = (GstPad *) g_value_get_object(&element);
+                               if (!gst_pad_is_linked(pad)) {
+                                       unlinked_pad_found = TRUE;
+                               }
+                               g_value_reset(&element);
+                       }
+
+                       g_value_unset(&element);
+                       gst_iterator_free(pad_iterator);
 
+                       /* If found element is not linked yet, check it by klass */
+                       if (unlinked_pad_found) {
+                               if (bin_name == NULL || g_strrstr(GST_ELEMENT_NAME(found_element), bin_name)) {
+                                       found = TRUE;
+                                       break;
+                               }
+                       }
+               }
+               unlinked_pad_found = FALSE;
                g_value_reset(&elem);
        }
 
@@ -375,15 +402,45 @@ static GstElement *__ms_bin_find_element_by_klass(GstElement *sink_bin, const gc
        return found ? found_element : NULL;
 }
 
+int __ms_get_rank_increase(const char *factory_class)
+{
+       gint rank_priority = 20;
+       gint rank_second = 10;
+       gint ret = 0;
+
+       if (g_strrstr(factory_class, "Dsp"))
+               ret = rank_priority;
+       else if (g_strrstr(factory_class, "HW"))
+               ret = rank_priority;
+       else if (g_strrstr(factory_class, "Arm"))
+               ret = rank_second;
+
+       return ret;
+}
+
+int __ms_factory_rank_compare(GstPluginFeature *first_feature, GstPluginFeature *second_feature)
+{
+       const gchar *class;
+       int first_feature_rank_inc=0, second_feature_rank_inc = 0;
+
+       class = gst_element_factory_get_klass(GST_ELEMENT_FACTORY(first_feature));
+               first_feature_rank_inc = __ms_get_rank_increase(class);
+       class = gst_element_factory_get_klass(GST_ELEMENT_FACTORY(second_feature));
+               second_feature_rank_inc = __ms_get_rank_increase(class);
+
+       return (gst_plugin_feature_get_rank(second_feature) + second_feature_rank_inc) -
+                (gst_plugin_feature_get_rank(first_feature) + first_feature_rank_inc );
+}
+
 gboolean __ms_feature_filter(GstPluginFeature *feature, gpointer data)
 {
-       if (!GST_IS_ELEMENT_FACTORY(feature))
+       if (!GST_IS_ELEMENT_FACTORY(feature)) {
                return FALSE;
-
+       }
        return TRUE;
 }
 
-static GstElement *__ms_create_element_by_registry(GstPad *src_pad, const gchar *klass_name)
+GstElement *__ms_create_element_by_registry(GstPad *src_pad, const gchar *klass_name)
 {
        GList *factories;
        const GList *pads;
@@ -394,6 +451,7 @@ static GstElement *__ms_create_element_by_registry(GstPad *src_pad, const gchar
 
        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);
@@ -411,7 +469,7 @@ static GstElement *__ms_create_element_by_registry(GstPad *src_pad, const gchar
                                }
 
                                if (GST_IS_CAPS(&pad_temp->static_caps.caps)) {
-                                       static_caps = gst_caps_ref(&pad_temp->static_caps.caps);
+                                       static_caps = gst_caps_ref(pad_temp->static_caps.caps);
                                } else {
                                        static_caps = gst_caps_from_string(pad_temp->static_caps.string);
                                }
@@ -432,76 +490,235 @@ static GstElement *__ms_create_element_by_registry(GstPad *src_pad, const gchar
        return next_element;
 }
 
-static GstElement *__ms_link_with_new_element (GstElement *previous_element, GstElement *new_element)
+GstElement * __ms_link_with_new_element(GstElement *previous_element,
+                                        GstElement *new_element,
+                                        const gchar *next_elem_bin_name)
 {
-       gboolean ret = gst_element_link_pads_filtered(previous_element, NULL, new_element, NULL, NULL);
+       GstCaps *new_pad_caps = NULL;
+       GstStructure *new_pad_struct = NULL;
+       const gchar *new_pad_type = NULL;
 
-       if (!ret) {
-               ms_error("Failed to link [%s] and [%s] \n", GST_ELEMENT_NAME(previous_element),
-                                GST_ELEMENT_NAME(new_element));
-               new_element = NULL;
+       GValue element = G_VALUE_INIT;
+       GstPad *sink_pad = NULL;
+       GstPad *src_pad = NULL;
+       GstIterator *pad_iterator = NULL;
+
+       if (next_elem_bin_name) {
+               pad_iterator = gst_element_iterate_sink_pads(new_element);
+               while (GST_ITERATOR_OK == gst_iterator_next(pad_iterator, &element))
+               {
+                       sink_pad = (GstPad *)g_value_get_object(&element);
+                       src_pad = gst_element_get_static_pad(previous_element, "sink");
+
+                       new_pad_caps = gst_pad_query_caps(src_pad, 0);
+                       new_pad_struct = gst_caps_get_structure(new_pad_caps, 0);
+                       new_pad_type = gst_structure_get_name(new_pad_struct);
+
+                       if (!gst_pad_is_linked(sink_pad)) {
+                               if(!strncmp(new_pad_type,GST_PAD_NAME(sink_pad), COMPARED_NUMBER)) {
+                                       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));
+                                       } else {
+                                               ms_error("Failed to link [%s] -> [%s]\n",
+                                                         GST_ELEMENT_NAME(previous_element),
+                                                         GST_ELEMENT_NAME(new_element));
+                                       }
+                               }
+                       }
+                       g_value_reset(&element);
+               }
+               g_value_unset(&element);
+               gst_iterator_free(pad_iterator);
        } else {
-               ms_info("Succeeded to link [%s] -> [%s]\n", GST_ELEMENT_NAME(previous_element),
-                                GST_ELEMENT_NAME(new_element));
-       }
+               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));
+               } else {
+                       ms_error("Failed to link [%s] and [%s] \n",
+                     GST_ELEMENT_NAME(previous_element),
+                     GST_ELEMENT_NAME(new_element));
+                       new_element = NULL;
+               }
+       }
        return new_element;
 }
 
-void __decodebin_newpad_cb(GstElement *decodebin, GstPad *new_pad, gpointer user_data)
+GstElement *__ms_combine_next_element(GstElement *previous_element,
+                                      const gchar *next_elem_klass_name,
+                                      const gchar *next_elem_bin_name,
+                                      const gchar *element_type,
+                                      gchar *default_element)
 {
-       GstElement *previous_element = NULL;
        GstElement *found_element = NULL;
-       GstElement *parent = NULL;
+       GstElement *parent_element = NULL;
+
+       char *plugin_name = NULL;
+       char *format_prefix = NULL;
+
+       media_format_h vfmt_encoded = NULL;
+       media_format_create(&vfmt_encoded);
+       if (media_format_set_video_mime(vfmt_encoded, MEDIA_FORMAT_H264_SP) != MEDIA_FORMAT_ERROR_NONE) {
+               ms_error("media_format_set_video_mime failed!\n");
+       }
+
+       media_format_set_video_width(vfmt_encoded, 1280);
+       media_format_set_video_height(vfmt_encoded, 720);
+       media_format_set_video_avg_bps(vfmt_encoded, 1031);
+       media_format_set_video_max_bps(vfmt_encoded, 2063);
+
+       parent_element = (GstElement *)gst_element_get_parent(previous_element);
+
+       /*Look for node created by user*/
+       if (next_elem_klass_name) {
+               found_element = __ms_bin_find_element_by_klass(parent_element, next_elem_klass_name, next_elem_bin_name);
+       }
+
+       /* Link with found node created by user*/
+       if (found_element && !element_type) {
+               previous_element = __ms_link_with_new_element(previous_element, found_element, next_elem_bin_name);
+       } else {
+
+               /* Check if rtp_container was created*/
+               if (!found_element && next_elem_bin_name && !element_type) {
+                       ms_error("Bin [%s] was not found", next_elem_bin_name);
+                       return NULL;
+
+               /* Create element by element name*/
+               } else if(!found_element && !next_elem_klass_name) {
+                       found_element = __ms_element_create(default_element, NULL);
+
+               /* Create element by predefined format element type*/
+               } else if(!found_element && element_type) {
+
+                       dictionary *dict = NULL;
+                       media_format_mimetype_e mime;
+
+                       if (MEDIA_FORMAT_ERROR_NONE != media_format_get_video_info(vfmt_encoded, &mime,
+                                                                                   NULL, NULL, NULL, NULL)) {
+                               media_format_get_audio_info(vfmt_encoded, &mime, NULL, NULL, NULL, NULL);
+                       }
+
+                       __ms_load_ini_dictionary(&dict);
+
+                       format_prefix = g_strdup_printf("%s:%s", __ms_convert_mime_to_string(mime), element_type);
+                       plugin_name = __ms_ini_get_string(dict, format_prefix, default_element);
+
+                       if (MS_ELEMENT_IS_ENCODER(next_elem_bin_name)) {
+                               if (MS_ELEMENT_IS_VIDEO(next_elem_bin_name)) {
+                                       found_element = __ms_video_encoder_element_create(dict, mime);
+                               } else if (MS_ELEMENT_IS_AUDIO(next_elem_bin_name)) {
+                                       found_element = __ms_audio_encoder_element_create();
+                               }
+                       } else if (MS_ELEMENT_IS_DECODER(next_elem_bin_name)) {
+                               if (MS_ELEMENT_IS_VIDEO(next_elem_bin_name)) {
+                                       found_element = __ms_video_decoder_element_create(dict, mime);
+                               }
+                       }
+
+                       __ms_destroy_ini_dictionary(dict);
+
+               /* Create element by caps of the previous element */
+               } else if (!found_element) {
+                       GstPad *src_pad = gst_element_get_static_pad(previous_element, "src");
+                       found_element = __ms_create_element_by_registry(src_pad, next_elem_klass_name);
+                       MS_SAFE_UNREF(src_pad);
+               }
+
+               /*Add created element*/
+               if (found_element && gst_bin_add(GST_BIN(parent_element), found_element)) {
+                       ms_debug("Element [%s] added into [%s] bin",
+                                 GST_ELEMENT_NAME(found_element),
+                                 GST_ELEMENT_NAME(parent_element));
+               } else {
+                       ms_error("Element [%s] was not added into [%s] bin",
+                                 GST_ELEMENT_NAME(found_element),
+                                 GST_ELEMENT_NAME(parent_element));
+               }
+               previous_element = __ms_link_with_new_element(previous_element, found_element, NULL);
+       }
+
+       gst_element_sync_state_with_parent(found_element);
+       __ms_generate_dots(parent_element, GST_ELEMENT_NAME(found_element));
+
+       MS_SAFE_FREE(plugin_name);
+       MS_SAFE_FREE(format_prefix);
+
+       return found_element;
+}
+
+
+void __decodebin_newpad_streamer_cb(GstElement *decodebin, GstPad *new_pad, gpointer user_data)
+{
+       media_streamer_s *ms_streamer = (media_streamer_s *)user_data;
+       ms_retm_if(ms_streamer == NULL, "Handle is NULL");
+
+       GstElement *found_element = NULL;
 
        GstCaps *new_pad_caps = NULL;
        GstStructure *new_pad_struct = NULL;
        const gchar *new_pad_type = NULL;
 
-       ms_info("Received new pad '%s' from [%s]", GST_PAD_NAME(new_pad), GST_ELEMENT_NAME(decodebin));
-       parent = (GstElement *)gst_element_get_parent(GST_OBJECT_CAST(decodebin));
+       ms_info("Received new pad '%s' from [%s]\n", 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);
+       new_pad_caps = gst_pad_query_caps(new_pad, 0);
        new_pad_struct = gst_caps_get_structure(new_pad_caps, 0);
        new_pad_type = gst_structure_get_name(new_pad_struct);
 
-       if (g_str_has_prefix(new_pad_type, "video")) {
-               found_element = __ms_element_create("videoconvert", NULL);
-       } else if (g_str_has_prefix(new_pad_type, "audio")) {
-               found_element = __ms_element_create("audioconvert", NULL);
-       } else {
-               ms_error("Could not create converting element according to media pad type");
+       if (g_str_has_prefix(new_pad_type, "video"))
+       {
+               found_element = __ms_combine_next_element(decodebin, NULL, NULL, NULL, DEFAULT_QUEUE);
+               found_element = __ms_combine_next_element(found_element, MEDIA_STREAMER_BIN_KLASS, "video_encoder", "encoder", DEFAULT_VIDEO_ENCODER);
+               found_element = __ms_combine_next_element(found_element, MEDIA_STREAMER_PAYLOADER_KLASS, NULL, NULL, NULL);
+               found_element = __ms_combine_next_element(found_element, MEDIA_STREAMER_BIN_KLASS, "rtp_container", NULL, NULL);
        }
 
-       if (!gst_bin_add(GST_BIN(parent), found_element)) {
-               ms_error("Failed to add element [%s] into bin [%s]", GST_ELEMENT_NAME(found_element),
-                               GST_ELEMENT_NAME(parent));
-       }
-       gst_element_sync_state_with_parent(found_element);
+       if (g_str_has_prefix(new_pad_type, "audio")) {
 
-       previous_element = __ms_link_with_new_element(decodebin, found_element);
-       if (!previous_element) {
-               gst_bin_remove(GST_BIN(parent), found_element);
+               found_element = __ms_combine_next_element(decodebin, NULL, NULL, NULL, DEFAULT_QUEUE);
+               found_element = __ms_combine_next_element(found_element, NULL, NULL, NULL, DEFAULT_AUDIO_CONVERT);
+               found_element = __ms_combine_next_element(found_element, MEDIA_STREAMER_PAYLOADER_KLASS, NULL, NULL, NULL);
+               found_element = __ms_combine_next_element(found_element, MEDIA_STREAMER_BIN_KLASS, "rtp_container", NULL, NULL);
        }
+}
 
+void __decodebin_newpad_cb(GstElement *decodebin, GstPad *new_pad, gpointer user_data)
+{
+       media_streamer_s *ms_streamer = (media_streamer_s *)user_data;
+       ms_retm_if(ms_streamer == NULL, "Handle is NULL");
 
-       /* Getting Sink */
-       found_element = __ms_bin_find_element_by_klass(parent, MEDIA_STREAMER_SINK_KLASS);
-       if (!found_element) {
-               ms_error("There are no any SINK elements created by user");
-       }
-       gst_element_sync_state_with_parent(found_element);
+       GstElement *found_element = NULL;
+
+       GstCaps *new_pad_caps = NULL;
+       GstStructure *new_pad_struct = NULL;
+       const gchar *new_pad_type = NULL;
+
+       ms_info("Received new pad '%s' from [%s]", GST_PAD_NAME(new_pad), GST_ELEMENT_NAME(decodebin));
 
-       previous_element = __ms_link_with_new_element(previous_element, found_element);
-       if (!previous_element) {
-               gst_bin_remove(GST_BIN(parent), found_element);
+       /* Check the new pad's type */
+       new_pad_caps = gst_pad_query_caps(new_pad, 0);
+       new_pad_struct = gst_caps_get_structure(new_pad_caps, 0);
+       new_pad_type = gst_structure_get_name(new_pad_struct);
+
+       if(MS_ELEMENT_IS_VIDEO(new_pad_type)) {
+               found_element = __ms_combine_next_element(decodebin, NULL, NULL, NULL, DEFAULT_VIDEO_CONVERT);
+       } else if (MS_ELEMENT_IS_AUDIO(new_pad_type)) {
+               found_element = __ms_combine_next_element(decodebin, NULL, NULL, NULL, DEFAULT_AUDIO_CONVERT);
        }
 
-       __ms_element_set_state(parent, GST_STATE_PLAYING);
+       /* Getting Sink */
+       found_element = __ms_combine_next_element(found_element, MEDIA_STREAMER_SINK_KLASS, NULL, NULL, NULL);
+       __ms_generate_dots(ms_streamer->pipeline, "pipeline_linked");
 }
 
-static gboolean __ms_sink_bin_prepare(media_streamer_node_s *ms_node, GstElement *sink_bin, GstPad *source_pad)
+static gboolean __ms_sink_bin_prepare(media_streamer_node_s *ms_node,
+                                      GstElement *sink_bin, GstPad *source_pad)
 {
        GstPad *src_pad = NULL;
        gboolean decodebin_usage = FALSE;
@@ -512,166 +729,81 @@ static gboolean __ms_sink_bin_prepare(media_streamer_node_s *ms_node, GstElement
        GstStructure *new_pad_struct = NULL;
        const gchar *new_pad_type = NULL;
 
-
        /* Getting Depayloader */
-       found_element = __ms_bin_find_element_by_klass(sink_bin, MEDIA_STREAMER_DEPAYLOADER_KLASS);
+       found_element = __ms_bin_find_element_by_klass(sink_bin, MEDIA_STREAMER_DEPAYLOADER_KLASS,
+                                                       MEDIA_STREAMER_NODE_TYPE_NONE);
 
        if (!found_element) {
                found_element = __ms_create_element_by_registry(source_pad, MEDIA_STREAMER_DEPAYLOADER_KLASS);
-               if (!gst_bin_add(GST_BIN(sink_bin), found_element)) {
-                       ms_error("Failed to add element [%s] into bin [%s]", GST_ELEMENT_NAME(found_element),
+               if (gst_bin_add(GST_BIN(sink_bin), found_element)) {
+                       ms_debug("Succeeded to add element [%s] into bin [%s]",
+                     GST_ELEMENT_NAME(found_element),
+                     GST_ELEMENT_NAME(sink_bin));
+               } else {
+                       ms_error("Failed to add element [%s] into bin [%s]",
+                     GST_ELEMENT_NAME(found_element),
                      GST_ELEMENT_NAME(sink_bin));
                }
        }
+
        previous_element = found_element;
        src_pad = gst_element_get_static_pad(found_element, "src");
 
        __ms_add_ghostpad(found_element, "sink", sink_bin, "sink");
 
+       previous_element = __ms_combine_next_element(previous_element, NULL, NULL, NULL, DEFAULT_QUEUE);
 
        /* Getting Decodebin */
        decodebin_usage = ms_node->parent_streamer->ini.use_decodebin;
-
-       found_element = __ms_bin_find_element_by_klass(sink_bin, MEDIA_STREAMER_DECODEBIN_KLASS);
+       found_element = __ms_bin_find_element_by_klass(sink_bin, MEDIA_STREAMER_BIN_KLASS, MEDIA_STREAMER_NODE_TYPE_NONE);
 
        if (!found_element) {
                if (decodebin_usage) {
-                       found_element = __ms_create_element_by_registry(src_pad, MEDIA_STREAMER_DECODEBIN_KLASS);
-                       if (!found_element) {
-                               ms_error("Could not create element of MEDIA_STREAMER_DECODER_KLASS");
-                       }
-                       if (!gst_bin_add(GST_BIN(sink_bin), found_element)) {
-                               ms_error("Failed to add element [%s] into bin [%s]", GST_ELEMENT_NAME(found_element),
-                                                GST_ELEMENT_NAME(sink_bin));
-                       }
-                       if (ms_node->parent_streamer->ini.use_decodebin) {
-                               g_signal_connect(found_element, "pad-added", G_CALLBACK(__decodebin_newpad_cb), (gpointer)ms_node);
-                       }
-
-                       previous_element = __ms_link_with_new_element(previous_element, found_element);
-                       if (!previous_element) {
-                               gst_bin_remove(sink_bin, found_element);
-                               return FALSE;
-                       }
+                       previous_element = __ms_combine_next_element(previous_element, MEDIA_STREAMER_BIN_KLASS, NULL, NULL, NULL);
+                       g_signal_connect(previous_element, "pad-added", G_CALLBACK(__decodebin_newpad_cb), (gpointer )ms_node);
                } else {
-
                        src_pad = gst_element_get_static_pad(previous_element, "src");
                        new_pad_caps = gst_pad_query_caps(src_pad, 0);
                        new_pad_struct = gst_caps_get_structure(new_pad_caps, 0);
                        new_pad_type = gst_structure_get_name(new_pad_struct);
 
-                       if (g_str_has_prefix(new_pad_type, "video")) {
-
-                               /* Getting Parser */
-                               found_element = __ms_bin_find_element_by_klass(sink_bin, MEDIA_STREAMER_PARSER_KLASS);
-                               if (!found_element) {
-                                       found_element = __ms_create_element_by_registry(src_pad, MEDIA_STREAMER_PARSER_KLASS);
-                                       if (!found_element) {
-                                               ms_error("Could not create element of MEDIA_STREAMER_PARSER_KLASS");
-                                       }
-                                       if (!gst_bin_add(GST_BIN(sink_bin), found_element)) {
-                                               ms_error("Failed to add element [%s] into bin [%s]", GST_ELEMENT_NAME(found_element),
-                                                                GST_ELEMENT_NAME(sink_bin));
-                                       }
-                               }
-                               previous_element = __ms_link_with_new_element(previous_element, found_element);
-                               if (!previous_element) {
-                                       gst_bin_remove(GST_BIN(sink_bin), found_element);
-                                       return FALSE;
-                               }
-                               src_pad = gst_element_get_static_pad(found_element, "src");
-
-
-                               /* Getting Decoder */
-                               found_element = __ms_bin_find_element_by_klass(sink_bin, MEDIA_STREAMER_DECODER_KLASS);
-                               if (!found_element) {
-                                       found_element = __ms_create_element_by_registry(src_pad, MEDIA_STREAMER_DECODER_KLASS);
-                                       if (!found_element) {
-                                               ms_error("Could not create element of MEDIA_STREAMER_DECODER_KLASS");
-                                       }
-                                       if (!gst_bin_add(GST_BIN(sink_bin), found_element)) {
-                                               ms_error("Failed to add element [%s] into bin [%s]", GST_ELEMENT_NAME(found_element),
-                                                                GST_ELEMENT_NAME(sink_bin));
-                                       }
-                               }
-                               previous_element = __ms_link_with_new_element(previous_element, found_element);
-                               if (!previous_element) {
-                                       gst_bin_remove(GST_BIN(sink_bin), found_element);
-                                       return FALSE;
-                               }
-                               src_pad = gst_element_get_static_pad(found_element, "src");
-
-
-                               /* Getting Convertor */
-                               found_element = __ms_element_create("videoconvert", NULL);
-
-                       } else if (g_str_has_prefix(new_pad_type, "audio")) {
-                               found_element = __ms_element_create("audioconvert", NULL);
-                       } else {
-                               ms_error("Could not create converting element according to media pad type");
+                       /* Getting elements if Decodebin is not used */
+                       if(MS_ELEMENT_IS_VIDEO(new_pad_type)) {
+                               previous_element = __ms_combine_next_element(previous_element, MEDIA_STREAMER_PARSER_KLASS, NULL, NULL, NULL);
+                               previous_element = __ms_combine_next_element(previous_element, MEDIA_STREAMER_DECODER_KLASS, NULL, NULL, NULL);
+                               previous_element = __ms_combine_next_element(previous_element, NULL, NULL, NULL, DEFAULT_QUEUE);
+                               previous_element = __ms_combine_next_element(previous_element, NULL, NULL, NULL, DEFAULT_VIDEO_CONVERT);
                        }
-
-                       if (!found_element) {
-                               ms_error("Could not create element of MEDIA_STREAMER_CONVERTER_KLASS");
-                       }
-                       if (!gst_bin_add(GST_BIN(sink_bin), found_element)) {
-                               ms_error("Failed to add element [%s] into bin [%s]", GST_ELEMENT_NAME(found_element),
-                                                GST_ELEMENT_NAME(sink_bin));
-                       }
-                       previous_element = __ms_link_with_new_element(previous_element, found_element);
-                       if (!previous_element) {
-                               gst_bin_remove(GST_BIN(sink_bin), found_element);
-                               return FALSE;
+                       if(MS_ELEMENT_IS_AUDIO(new_pad_type)) {
+                               previous_element = __ms_combine_next_element(previous_element, NULL, NULL, NULL, DEFAULT_AUDIO_CONVERT);
                        }
 
-
-               /* Getting Sink */
-               found_element = __ms_bin_find_element_by_klass(sink_bin, MEDIA_STREAMER_SINK_KLASS);
-               if (!found_element) {
-                       ms_error("There are no any SINK elements created by user");
-               }
-               previous_element = __ms_link_with_new_element(previous_element, found_element);
-               if (!previous_element) {
-                       gst_bin_remove(GST_BIN(sink_bin), found_element);
-                       return FALSE;
-               }
-
-               __ms_generate_dots(ms_node->parent_streamer->pipeline, "pipeline_linked");
-               __ms_element_set_state(ms_node->parent_streamer->pipeline, GST_STATE_PLAYING);
+                       /* Getting Sink  */
+                       previous_element = __ms_combine_next_element(previous_element, MEDIA_STREAMER_SINK_KLASS, NULL, NULL, NULL);
                }
 
        } else {
-               if(!gst_pad_is_linked(src_pad)) {
-                       previous_element = __ms_link_with_new_element(previous_element, found_element);
-                       if (!previous_element) {
-                               gst_bin_remove(GST_BIN(sink_bin), found_element);
-                               return FALSE;
-                       }
+
+               /* If decode element was added but not linked yet */
+               if (!gst_pad_is_linked(src_pad)) {
+                       previous_element = __ms_link_with_new_element(previous_element, found_element, NULL);
                } else {
+
+                       /* If decode element was added and linked */
                        previous_element = found_element;
                }
 
+               /* If decode element was made by user, not decodebin */
                if (!decodebin_usage) {
 
-                       /* Getting Sink */
-                       found_element = __ms_bin_find_element_by_klass(sink_bin, MEDIA_STREAMER_SINK_KLASS);
-                       if (!found_element) {
-                               ms_error("There are no any SINK elements created by user");
+                       /* Find sink element and link with it, if it was not linked yet */
+                       previous_element = __ms_combine_next_element(previous_element, MEDIA_STREAMER_SINK_KLASS, NULL,NULL, NULL);
+                       if (!gst_pad_is_linked(src_pad)) {
+                               previous_element = __ms_link_with_new_element(previous_element, found_element, NULL);
                        }
-
-                       if(!gst_pad_is_linked(src_pad)) {
-                               previous_element = __ms_link_with_new_element(previous_element, found_element);
-                               if (!previous_element) {
-                                       gst_bin_remove(GST_BIN(sink_bin), found_element);
-                                       return FALSE;
-                               }
-                       }
-
-                       __ms_generate_dots(ms_node->parent_streamer->pipeline, "pipeline_linked");
-                       __ms_element_set_state(ms_node->parent_streamer->pipeline, GST_STATE_PLAYING);
                }
        }
-
+       __ms_generate_dots(ms_node->parent_streamer->pipeline, "pipeline_linked");
        MS_SAFE_UNREF(src_pad);
 
        return TRUE;
@@ -808,7 +940,7 @@ GstElement *__ms_camera_element_create(const char *camera_plugin_name)
        return camera_bin;
 }
 
-GstElement *__ms_video_encoder_element_create(dictionary *dict , media_format_mimetype_e mime)
+GstElement *__ms_video_encoder_element_create(dictionary *dict, media_format_mimetype_e mime)
 {
        char *plugin_name = NULL;
        char *format_prefix = NULL;
@@ -852,7 +984,7 @@ GstElement *__ms_video_encoder_element_create(dictionary *dict , media_format_mi
        return encoder_bin;
 }
 
-GstElement *__ms_video_decoder_element_create(dictionary *dict , media_format_mimetype_e mime)
+GstElement *__ms_video_decoder_element_create(dictionary *dict, media_format_mimetype_e mime)
 {
        char *plugin_name = NULL;
        char *format_prefix = NULL;
@@ -870,7 +1002,7 @@ GstElement *__ms_video_decoder_element_create(dictionary *dict , media_format_mi
        GstElement *decoder_parser = __ms_element_create(plugin_name, NULL);
 
        if (mime == MEDIA_FORMAT_H264_SP) {
-               g_object_set(G_OBJECT(decoder_parser), "config-interval", 5, NULL);
+               g_object_set(G_OBJECT(decoder_parser), "config-interval", COMPARED_NUMBER, NULL);
        }
 
        if (g_strrstr(format_prefix, "omx")) {
@@ -996,6 +1128,7 @@ gboolean __ms_get_rtp_elements(media_streamer_node_s *ms_node,
                gst_bin_add_many(GST_BIN(ms_node->gst_element),
                                 *rtp_elem, *rtcp_elem, NULL);
        } else {
+
                /*rtp/rtcp elements already into rtp bin. */
                MS_SAFE_GFREE(rtp_elem_name);
                MS_SAFE_GFREE(rtcp_elem_name);
@@ -1080,10 +1213,6 @@ int __ms_add_node_into_bin(media_streamer_s *ms_streamer, media_streamer_node_s
                        gst_ret = gst_bin_add(GST_BIN(ms_streamer->topology_bin), ms_node->gst_element);
                        bin_name = g_strdup(MEDIA_STREAMER_TOPOLOGY_BIN_NAME);
                        break;
-               case MEDIA_STREAMER_NODE_TYPE_VIDEO_DECODER:
-                       gst_ret = gst_bin_add(GST_BIN(ms_streamer->sink_video_bin), ms_node->gst_element);
-                       bin_name = g_strdup(MEDIA_STREAMER_VIDEO_SINK_BIN_NAME);
-                       break;
                case MEDIA_STREAMER_NODE_TYPE_VIDEO_DEPAY:
                        gst_ret = gst_bin_add(GST_BIN(ms_streamer->sink_video_bin), ms_node->gst_element);
                        bin_name = g_strdup(MEDIA_STREAMER_VIDEO_SINK_BIN_NAME);
index 224b44f..e37bd6f 100755 (executable)
@@ -45,9 +45,9 @@ char *param_table[PROPERTY_COUNT][2] = {
        {MEDIA_STREAMER_PARAM_HOST, "host"}
 };
 
-static int __ms_node_set_property(media_streamer_node_s *ms_node,
-                                  const gchar *param_key,
-                                  const gchar *param_value)
+int __ms_node_set_property(media_streamer_node_s *ms_node,
+                           const gchar *param_key,
+                           const gchar *param_value)
 {
        ms_retvm_if(!ms_node && !ms_node->gst_element, MEDIA_STREAMER_ERROR_INVALID_OPERATION, "Error: empty node");
        ms_retvm_if(!param_key && !param_value, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Error: invalid property parameter");
@@ -95,7 +95,7 @@ static int __ms_rtp_node_set_property(media_streamer_node_s *ms_node,
 
                g_strfreev(tokens);
                return MEDIA_STREAMER_ERROR_NONE;
-       } else if (tokens || tokens[0] || tokens[1] || tokens[2]) {
+       } else if (tokens && tokens[0] && tokens[1] && tokens[2]) {
 
                /*
                 * Rtp node parameter name consist of three fields separated with symbol '_':
@@ -278,7 +278,7 @@ int __ms_src_node_create(media_streamer_node_s *node)
 
        switch (node->subtype) {
                case MEDIA_STREAMER_NODE_SRC_TYPE_FILE:
-                       ms_error("Error: not implemented yet");
+                       node->gst_element = __ms_element_create("filesrc", NULL);
                        break;
                case MEDIA_STREAMER_NODE_SRC_TYPE_RTSP:
                        node->gst_element = __ms_element_create(DEFAULT_UDP_SOURCE, NULL);
@@ -459,63 +459,94 @@ int __ms_node_remove_from_table(GHashTable *nodes_table,
        return MEDIA_STREAMER_ERROR_NONE;
 }
 
+static gboolean __ms_src_need_typefind(GstElement *src)
+{
+       gboolean ret = FALSE;
+       g_assert(src);
+
+       GstPad *src_pad = gst_element_get_static_pad(src, "src");
+       if (!src_pad || gst_pad_is_linked(src_pad)) {
+               MS_SAFE_UNREF(src_pad);
+               return FALSE;
+       }
+
+       GstCaps *src_caps = gst_pad_query_caps(src_pad, NULL);
+       if (gst_caps_is_any(src_caps)) {
+               ret = TRUE;
+       }
+
+       gst_caps_unref(src_caps);
+       MS_SAFE_UNREF(src_pad);
+       return ret;
+}
+
 int __ms_autoplug_prepare(media_streamer_s *ms_streamer)
 {
        GstElement *unlinked_element = NULL;
        GstPad *unlinked_pad = NULL;
-       gchar *unlinked_element_name = NULL;
 
-       ms_retvm_if(ms_streamer == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER,
-                   "Handle is NULL");
+       GstElement *parent;
+       GstElement *found_element;
+
+       GstCaps *new_pad_caps = NULL;
+       GstStructure *new_pad_struct = NULL;
+       const gchar *new_pad_type = NULL;
+
+       ms_retvm_if(ms_streamer == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Handle is NULL");
 
-       /*Find unlinked element into src_bin */
+       /* Find unlinked element in src_bin */
        unlinked_pad = gst_bin_find_unlinked_pad(GST_BIN(ms_streamer->src_bin), GST_PAD_SRC);
+
        while (unlinked_pad)
        {
-               GstCaps *pad_caps = gst_pad_query_caps(unlinked_pad, NULL);
-               GstStructure *src_pad_struct = gst_caps_get_structure(pad_caps, 0);
-               const gchar *field = gst_structure_get_name(src_pad_struct);
-
                unlinked_element = gst_pad_get_parent_element(unlinked_pad);
-               unlinked_element_name = gst_element_get_name(unlinked_element);
-               ms_debug("Autoplug: found unlinked element [%s] in src_bin with pad type [%s].",
-                               unlinked_element_name, field);
-
-               /*find elements into topology */
-               GstPad *unlinked_topo_pad = gst_bin_find_unlinked_pad(GST_BIN(ms_streamer->topology_bin), GST_PAD_SINK);
-               GstElement *unlinked_topo_element = gst_pad_get_parent_element(unlinked_topo_pad);
-               gchar *unlinked_topo_pad_name = gst_pad_get_name(unlinked_topo_pad);
-
-               GstElement *encoder;
-               GstElement *pay;
-               if (MS_ELEMENT_IS_VIDEO(field)) {
-                       dictionary *dict = NULL;
-                       __ms_load_ini_dictionary(&dict);
-
-                       encoder = __ms_video_encoder_element_create(dict, MEDIA_FORMAT_H263);
-                       pay = __ms_element_create(DEFAULT_VIDEO_RTPPAY, NULL);
-                       gst_bin_add_many(GST_BIN(ms_streamer->topology_bin), encoder, pay, NULL);
-
-                       __ms_destroy_ini_dictionary(dict);
-
-                       gst_element_link_many(unlinked_element, encoder, pay, NULL);
-                       gst_element_link_pads(pay, "src", unlinked_topo_element, unlinked_topo_pad_name);
-               } else if (MS_ELEMENT_IS_AUDIO(field)) {
-                       encoder = __ms_audio_encoder_element_create();
-                       pay = __ms_element_create(DEFAULT_AUDIO_RTPPAY, NULL);
-                       gst_bin_add_many(GST_BIN(ms_streamer->topology_bin), encoder, pay, NULL);
-
-                       gst_element_link_many(unlinked_element, encoder, pay, NULL);
-                       gst_element_link_pads(pay, "src", unlinked_topo_element, unlinked_topo_pad_name);
+               ms_debug("Autoplug: found unlinked element [%s]\n", GST_ELEMENT_NAME(unlinked_element));
+
+               parent = (GstElement *)gst_element_get_parent(GST_OBJECT_CAST(unlinked_element));
+               ms_info("Received new pad '%s' from [%s]\n", 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);
+
+                       gst_element_sync_state_with_parent(found_element);
+                       g_signal_connect(found_element, "pad-added", G_CALLBACK (__decodebin_newpad_streamer_cb), ms_streamer);
+
+                       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 {
-                       ms_debug("Autoplug mode doesn't support [%s] type nodes.", field);
-               }
 
-               MS_SAFE_GFREE(unlinked_topo_pad_name);
-               MS_SAFE_GFREE(unlinked_element_name);
-               MS_SAFE_UNREF(unlinked_pad);
-               gst_caps_unref(pad_caps);
+                       found_element = __ms_element_create(DEFAULT_QUEUE, NULL);
+                       gst_bin_add_many((GstBin *)ms_streamer->topology_bin, found_element, NULL);
+
+                       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);
+                       new_pad_struct = gst_caps_get_structure(new_pad_caps, 0);
+                       new_pad_type = gst_structure_get_name(new_pad_struct);
+
+                       if(MS_ELEMENT_IS_VIDEO(new_pad_type)) {
+                               found_element = __ms_combine_next_element(found_element, MEDIA_STREAMER_BIN_KLASS, "video_encoder", "encoder", DEFAULT_VIDEO_ENCODER);
+                               found_element = __ms_combine_next_element(found_element, MEDIA_STREAMER_PAYLOADER_KLASS, NULL, NULL, NULL);
+                               found_element = __ms_combine_next_element(found_element, MEDIA_STREAMER_BIN_KLASS, "rtp_container", NULL, NULL);
+                       }
+
+                       if(MS_ELEMENT_IS_AUDIO(new_pad_type)) {
+                               found_element = __ms_combine_next_element(found_element, MEDIA_STREAMER_BIN_KLASS, "audio_encoder", "encoder", DEFAULT_AUDIO_PARSER);
+                               found_element = __ms_combine_next_element(found_element, MEDIA_STREAMER_PAYLOADER_KLASS, NULL, NULL, NULL);
+                               found_element = __ms_combine_next_element(found_element, MEDIA_STREAMER_BIN_KLASS, "rtp_container", NULL, NULL);
+                       }
+                       __ms_generate_dots(parent, GST_ELEMENT_NAME(found_element));
+               }
                unlinked_pad = gst_bin_find_unlinked_pad(GST_BIN(ms_streamer->src_bin), GST_PAD_SRC);
        }
 
@@ -662,10 +693,10 @@ void __ms_node_check_param_name(GstElement *element, gboolean name_is_known,
        {
                set_param_name = param_table[it_param][0];
                orig_param_name = param_table[it_param][1];
+               param = g_object_class_find_property(G_OBJECT_GET_CLASS(element), orig_param_name);
 
                if (name_is_known) {
                        if(!g_strcmp0(param_name, set_param_name)) {
-                               param = g_object_class_find_property(G_OBJECT_GET_CLASS(element), orig_param_name);
                                if (param) {
                                        *init_param_name = orig_param_name;
                                        break;
@@ -673,7 +704,6 @@ void __ms_node_check_param_name(GstElement *element, gboolean name_is_known,
                        }
                } else {
                        if(!g_strcmp0(param_name, orig_param_name)) {
-                               param = g_object_class_find_property(G_OBJECT_GET_CLASS(element), orig_param_name);
                                if (param) {
                                        *init_param_name = set_param_name;
                                        break;
@@ -762,4 +792,4 @@ int __ms_node_write_param_into_value(media_streamer_node_s *node, const char *pa
        *param_value = string_val;
 
        return MEDIA_STREAMER_ERROR_NONE;
-}
\ No newline at end of file
+}
index 3223ecd..d14b5e4 100755 (executable)
@@ -32,10 +32,11 @@ typedef enum {
 } menu_state_e;
 
 typedef enum {
-       SUBMENU_STATE_UNKNOWN = 0,
+       SUBMENU_STATE_UNKNOWN,
        SUBMENU_STATE_GETTING_IP,
-       SUBMENU_STATE_AUTOPLUG = 3,
-       SUBMENU_STATE_SCENARIO = 4,
+       SUBMENU_STATE_GETTING_URI,
+       SUBMENU_STATE_AUTOPLUG,
+       SUBMENU_STATE_SCENARIO,
        SUBMENU_STATE_FORMAT
 } submenu_state_e;
 
@@ -56,14 +57,15 @@ typedef enum {
 
 typedef enum
 {
-       SCENARIO_MODE_UNKNOWN = 0,
-       SCENARIO_MODE_CAMERA_SCREEN = 1,
-       SCENARIO_MODE_MICROPHONE_PHONE = 2,
-       SCENARIO_MODE_FULL_VIDEO_AUDIO = 3,
-       SCENARIO_MODE_VIDEOTEST_SCREEN = 4,
-       SCENARIO_MODE_AUDIOTEST_PHONE = 5,
-       SCENARIO_MODE_TEST_VIDEO_AUDIO = 6,
-       SCENARIO_MODE_APPSRC_APPSINK = 7,
+       SCENARIO_MODE_UNKNOWN,
+       SCENARIO_MODE_CAMERA_SCREEN,
+       SCENARIO_MODE_MICROPHONE_PHONE,
+       SCENARIO_MODE_FULL_VIDEO_AUDIO,
+       SCENARIO_MODE_VIDEOTEST_SCREEN,
+       SCENARIO_MODE_AUDIOTEST_PHONE,
+       SCENARIO_MODE_TEST_VIDEO_AUDIO,
+       SCENARIO_MODE_FILESRC_VIDEO_AUDIO,
+       SCENARIO_MODE_APPSRC_APPSINK
 } scenario_mode_e;
 
 #define PACKAGE "media_streamer_test"
@@ -87,6 +89,7 @@ static media_streamer_h current_media_streamer = &g_media_streamer;
 GMainLoop *g_loop;
 
 gchar *g_broadcast_address = NULL;
+gchar *g_uri = NULL;
 menu_state_e g_menu_state = MENU_STATE_MAIN_MENU;
 submenu_state_e g_sub_menu_state = SUBMENU_STATE_UNKNOWN;
 preset_type_e g_menu_preset = PRESET_UNKNOWN;
@@ -336,9 +339,11 @@ static gboolean _create_rtp_streamer(media_streamer_node_h rtp_bin)
                } else if (g_scenario_mode == SCENARIO_MODE_VIDEOTEST_SCREEN ||
                    g_scenario_mode == SCENARIO_MODE_TEST_VIDEO_AUDIO) {
                        media_streamer_node_create_src(MEDIA_STREAMER_NODE_SRC_TYPE_VIDEO_TEST, &video_src);
+               } else if (g_scenario_mode == SCENARIO_MODE_FILESRC_VIDEO_AUDIO) {
+                       media_streamer_node_create_src( MEDIA_STREAMER_NODE_SRC_TYPE_FILE, &video_src);
+                       media_streamer_node_set_param(video_src,MEDIA_STREAMER_PARAM_URI, g_uri);
                }
 
-               media_streamer_node_set_param(video_src, "is-live", "true");
                media_streamer_node_add(current_media_streamer, video_src);
 
                /*********************** encoder **************************************** */
@@ -354,9 +359,9 @@ static gboolean _create_rtp_streamer(media_streamer_node_h rtp_bin)
                media_streamer_node_add(current_media_streamer, video_pay);
 
                /*====================Linking Video Streamer=========================== */
-               media_streamer_node_link(video_src, "src", video_enc, "sink");
-               media_streamer_node_link(video_enc, "src", video_pay, "sink");
-               media_streamer_node_link(video_pay, "src", rtp_bin, "video_in");
+               /* media_streamer_node_link(video_src, "src", video_enc, "sink"); */
+               /* media_streamer_node_link(video_enc, "src", video_pay, "sink"); */
+               /* media_streamer_node_link(video_pay, "src", rtp_bin, "video_in"); */
                /*====================================================================== */
 
                g_print("== success streamer video part \n");
@@ -388,9 +393,9 @@ static gboolean _create_rtp_streamer(media_streamer_node_h rtp_bin)
                media_streamer_node_add(current_media_streamer, audio_pay);
 
                /*====================Linking Audio Streamer========================== */
-               media_streamer_node_link(audio_src, "src", audio_enc, "sink");
-               media_streamer_node_link(audio_enc, "src", audio_pay, "sink");
-               media_streamer_node_link(audio_pay, "src", rtp_bin, "audio_in");
+               /* media_streamer_node_link(audio_src, "src", audio_enc, "sink"); */
+               /* media_streamer_node_link(audio_enc, "src", audio_pay, "sink"); */
+               /* media_streamer_node_link(audio_pay, "src", rtp_bin, "audio_in"); */
                /*====================================================================== */
 
                g_print("== success streamer audio part \n");
@@ -414,6 +419,9 @@ static gboolean _create_rtp_streamer_autoplug(media_streamer_node_h rtp_bin)
                } else if (g_scenario_mode == SCENARIO_MODE_VIDEOTEST_SCREEN ||
                    g_scenario_mode == SCENARIO_MODE_TEST_VIDEO_AUDIO) {
                        media_streamer_node_create_src(MEDIA_STREAMER_NODE_SRC_TYPE_VIDEO_TEST, &video_src);
+               } else if (g_scenario_mode == SCENARIO_MODE_FILESRC_VIDEO_AUDIO) {
+                       media_streamer_node_create_src( MEDIA_STREAMER_NODE_SRC_TYPE_FILE, &video_src);
+                       media_streamer_node_set_param(video_src,MEDIA_STREAMER_PARAM_URI, g_uri);
                }
 
                media_streamer_node_add(current_media_streamer, video_src);
@@ -465,8 +473,8 @@ static gboolean _create_rtp_client(media_streamer_node_h rtp_bin)
                media_streamer_node_add(current_media_streamer, video_sink);
 
                /*====================Linking Video Client=========================== */
-               media_streamer_node_link(video_depay, "src", video_dec, "sink");
-               media_streamer_node_link(video_dec, "src", video_sink, "sink");
+               /* media_streamer_node_link(video_depay, "src", video_dec, "sink"); */
+               /* media_streamer_node_link(video_dec, "src", video_sink, "sink"); */
 
                g_print("== success client video part \n");
        }
@@ -553,9 +561,10 @@ static void buffer_status_cb(media_streamer_node_h node,
                media_streamer_custom_buffer_status_e status,
                void *user_data) {
 
-       static int count = 0; /* Try send only 10 packets*/
-       if (status == MEDIA_STREAMER_CUSTOM_BUFFER_UNDERRUN
-                       && count < 10) {
+       static int count = 0;
+
+       /* Try send only 10 packets*/
+       if (status == MEDIA_STREAMER_CUSTOM_BUFFER_UNDERRUN && count < 10) {
                g_print("Buffer status cb got underflow\n");
 
                char *test = g_strdup_printf("[%d]This is buffer_status_cb test!", count);
@@ -587,7 +596,6 @@ static void new_buffer_cb(media_streamer_node_h node, void *user_data)
 
 static void eos_cb(media_streamer_node_h node, void *user_data)
 {
-
        g_print("Got EOS cb from appsink\n");
 }
 
@@ -648,6 +656,11 @@ void reset_current_menu_state(void)
                g_free(g_broadcast_address);
                g_broadcast_address = NULL;
        }
+
+       if (g_uri != NULL) {
+               g_free(g_uri);
+               g_uri = NULL;
+       }
 }
 
 void quit()
@@ -663,6 +676,12 @@ static void display_getting_ip_menu(void)
        g_print("By default will be used [%s]\n", DEFAULT_IP_ADDR);
 }
 
+static void display_getting_uri_menu(void)
+{
+       g_print("\n");
+       g_print("Please input URI for playing\n");
+}
+
 static void display_autoplug_select_menu(void)
 {
        g_print("\n");
@@ -685,7 +704,8 @@ static void display_scenario_select_menu(void)
        g_print("4. Video test -> Screen\n");
        g_print("5. Audio test -> Phones\n");
        g_print("6. Video test + Audio test -> Screen + Phones\n");
-       g_print("7. Appsrc -> Appsink\n");
+       g_print("7. Filesrc -> Screen + Phones\n");
+       g_print("8. Appsrc -> Appsink\n");
 }
 
 static void display_preset_menu(void)
@@ -775,6 +795,9 @@ static void display_menu(void)
                        case SUBMENU_STATE_GETTING_IP:
                                display_getting_ip_menu();
                                break;
+                       case SUBMENU_STATE_GETTING_URI:
+                               display_getting_uri_menu();
+                               break;
                        case SUBMENU_STATE_AUTOPLUG:
                                display_autoplug_select_menu();
                                break;
@@ -954,6 +977,14 @@ void _interpret_scenario_menu(char *cmd)
                        g_video_is_on = TRUE;
                        g_audio_is_on = TRUE;
                } else if (!strncmp(cmd, "7", len)) {
+                       g_scenario_mode = SCENARIO_MODE_FILESRC_VIDEO_AUDIO;
+                       g_video_is_on = TRUE;
+                       g_audio_is_on = TRUE;
+                       if (g_menu_preset & PRESET_RTP_STREAMER) {
+                               g_sub_menu_state = SUBMENU_STATE_GETTING_URI;
+                               return;
+                       }
+               } else if (!strncmp(cmd, "8", len)) {
                        g_scenario_mode = SCENARIO_MODE_APPSRC_APPSINK;
                        g_video_is_on = FALSE;
                        g_audio_is_on = FALSE;
@@ -983,6 +1014,23 @@ void _interpret_getting_ip_menu(char *cmd)
        g_sub_menu_state = SUBMENU_STATE_SCENARIO;
 }
 
+void _interpret_getting_uri_menu(char *cmd)
+{
+       if (cmd) {
+               if (g_uri != NULL) {
+                       g_free(g_uri);
+               }
+               g_uri = g_strdup(cmd);
+               g_print("== URI set to [%s]\n", g_uri);
+       } else {
+               g_print("Empty URI!\n");
+               return;
+       }
+
+       g_sub_menu_state = SUBMENU_STATE_UNKNOWN;
+       run_preset();
+}
+
 void _interpret_autoplug_menu(char *cmd)
 {
        int cmd_number = atoi(cmd) - 1;
@@ -1076,6 +1124,9 @@ static void interpret_cmd(char *cmd)
                        case SUBMENU_STATE_GETTING_IP:
                                _interpret_getting_ip_menu(cmd);
                                break;
+                       case SUBMENU_STATE_GETTING_URI:
+                               _interpret_getting_uri_menu(cmd);
+                               break;
                        case SUBMENU_STATE_AUTOPLUG:
                                _interpret_autoplug_menu(cmd);
                                break;