sync code with spin dev including ACR feedback 34/42834/2 accepted/tizen/mobile/20150710.122646 accepted/tizen/tv/20150710.122757 accepted/tizen/wearable/20150710.122835 submit/tizen/20150710.082558
authoreunhae1.choi <eunhae1.choi@samsung.com>
Fri, 3 Jul 2015 03:18:10 +0000 (12:18 +0900)
committereunhae1.choi <eunhae1.choi@samsung.com>
Mon, 6 Jul 2015 13:13:09 +0000 (22:13 +0900)
Change-Id: I123afa64a1ec52fe3ae25a9c9c5ef3b73d711677

include/media_streamer.h
include/media_streamer_gst.h
include/media_streamer_node.h
include/media_streamer_priv.h
include/media_streamer_util.h
src/media_streamer.c
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 04ac0b6..eb239fe 100755 (executable)
@@ -19,7 +19,6 @@
 
 #include <tizen.h>
 #include <bundle.h>
-#include <mm_message.h>
 #include <media_format.h>
 #include <media_packet.h>
 
@@ -56,21 +55,14 @@ typedef void *media_streamer_h;
 typedef void *media_streamer_node_h;
 
 /**
- * @brief Media streamer time type.
- *
- * @since_tizen 3.0
- */
-typedef long long media_streamer_time_value;
-
-/**
  * @brief Enumeration for media streamer node type.
  *
  * @since_tizen 3.0
  */
 typedef enum {
        MEDIA_STREAMER_NODE_TYPE_NONE,                 /**<  Not defined type */
-       MEDIA_STREAMER_NODE_TYPE_SRC,                  /**<  Src node type */
-       MEDIA_STREAMER_NODE_TYPE_SINK,                 /**<  Sink node type */
+       MEDIA_STREAMER_NODE_TYPE_SRC,                  /**<  Src node type. Not available for media_streamer_node_create(). Use media_streamer_node_create_src() */
+       MEDIA_STREAMER_NODE_TYPE_SINK,                 /**<  Sink node type. Not available for media_streamer_node_create(). Use media_streamer_node_create_sink() */
        MEDIA_STREAMER_NODE_TYPE_VIDEO_ENCODER,        /**<  Video encoder node type */
        MEDIA_STREAMER_NODE_TYPE_VIDEO_DECODER,        /**<  Video decoder node type */
        MEDIA_STREAMER_NODE_TYPE_AUDIO_ENCODER,        /**<  Audio encoder node type */
@@ -102,17 +94,17 @@ typedef enum {
  * @since_tizen 3.0
  */
 typedef enum {
-       MEDIA_STREAMER_SRC_TYPE_NONE,           /**<  Not defined src type */
-       MEDIA_STREAMER_SRC_TYPE_FILE,           /**<  Local file src type */
-       MEDIA_STREAMER_SRC_TYPE_HTTP,           /**<  Http src type */
-       MEDIA_STREAMER_SRC_TYPE_RTSP,           /**<  Rtsp src type */
-       MEDIA_STREAMER_SRC_TYPE_CAMERA,         /**<  Camera src type */
-       MEDIA_STREAMER_SRC_TYPE_AUDIO_CAPTURE,  /**<  Audio capture src type */
-       MEDIA_STREAMER_SRC_TYPE_VIDEO_CAPTURE,  /**<  Video capture src type */
-       MEDIA_STREAMER_SRC_TYPE_AUDIO_TEST,     /**<  Audio test src type */
-       MEDIA_STREAMER_SRC_TYPE_VIDEO_TEST,     /**<  Video test src type */
-       MEDIA_STREAMER_SRC_TYPE_CUSTOM          /**<  Custom src type */
-} media_streamer_src_type_e;
+       MEDIA_STREAMER_NODE_SRC_TYPE_NONE,           /**<  Not defined src type */
+       MEDIA_STREAMER_NODE_SRC_TYPE_FILE,           /**<  Local file src type */
+       MEDIA_STREAMER_NODE_SRC_TYPE_HTTP,           /**<  Http src type, Network internet feature is required */
+       MEDIA_STREAMER_NODE_SRC_TYPE_RTSP,           /**<  Rtsp src type, Network internet feature is required */
+       MEDIA_STREAMER_NODE_SRC_TYPE_CAMERA,         /**<  Camera src type, Camera feature is required */
+       MEDIA_STREAMER_NODE_SRC_TYPE_AUDIO_CAPTURE,  /**<  Audio capture src type, Microphone feature is required */
+       MEDIA_STREAMER_NODE_SRC_TYPE_VIDEO_CAPTURE,  /**<  Video capture src type, Camera feature is required */
+       MEDIA_STREAMER_NODE_SRC_TYPE_AUDIO_TEST,     /**<  Audio test src type */
+       MEDIA_STREAMER_NODE_SRC_TYPE_VIDEO_TEST,     /**<  Video test src type */
+       MEDIA_STREAMER_NODE_SRC_TYPE_CUSTOM          /**<  Custom src type */
+} media_streamer_node_src_type_e;
 
 /**
  * @brief Enumeration for media streamer sink node type.
@@ -120,15 +112,15 @@ typedef enum {
  * @since_tizen 3.0
  */
 typedef enum {
-       MEDIA_STREAMER_SINK_TYPE_NONE,   /**<  Not defined sink type */
-       MEDIA_STREAMER_SINK_TYPE_FILE,   /**<  Local file sink type */
-       MEDIA_STREAMER_SINK_TYPE_RTSP,   /**<  Rtsp sink type */
-       MEDIA_STREAMER_SINK_TYPE_HTTP,   /**<  Http sink type */
-       MEDIA_STREAMER_SINK_TYPE_AUDIO,  /**<  Audio sink type */
-       MEDIA_STREAMER_SINK_TYPE_SCREEN, /**<  Screen sink type */
-       MEDIA_STREAMER_SINK_TYPE_FAKE,   /**<  Fake sink type */
-       MEDIA_STREAMER_SINK_TYPE_CUSTOM  /**<  Custom sink type */
-} media_streamer_sink_type_e;
+       MEDIA_STREAMER_NODE_SINK_TYPE_NONE,   /**<  Not defined sink type */
+       MEDIA_STREAMER_NODE_SINK_TYPE_FILE,   /**<  Local file sink type */
+       MEDIA_STREAMER_NODE_SINK_TYPE_RTSP,   /**<  Rtsp sink type, Network internet feature is required */
+       MEDIA_STREAMER_NODE_SINK_TYPE_HTTP,   /**<  Http sink type, Network internet feature is required */
+       MEDIA_STREAMER_NODE_SINK_TYPE_AUDIO,  /**<  Audio sink type */
+       MEDIA_STREAMER_NODE_SINK_TYPE_SCREEN, /**<  Screen sink type */
+       MEDIA_STREAMER_NODE_SINK_TYPE_FAKE,   /**<  Fake sink type */
+       MEDIA_STREAMER_NODE_SINK_TYPE_CUSTOM  /**<  Custom sink type */
+} media_streamer_node_sink_type_e;
 
 /**
  * @brief Enumeration for media streamer state.
@@ -167,12 +159,209 @@ typedef enum {
  * @since_tizen 3.0
  */
 typedef enum {
-       MEDIA_STREAMER_CUSTOM_BUFFER_UNDERRUN,  /**< buffer underrun of custom src */
-       MEDIA_STREAMER_CUSTOM_BUFFER_OVERFLOW,  /**< buffer overflow of custom src */
+       MEDIA_STREAMER_CUSTOM_BUFFER_UNDERRUN,  /**< Buffer underrun of custom src */
+       MEDIA_STREAMER_CUSTOM_BUFFER_OVERFLOW,  /**< Buffer overflow of custom src */
 } media_streamer_custom_buffer_status_e;
 
 /**
+ * @brief Definition for "camera-id" parameter of source node.
+ * @details Index number of camera to activate.
+ *          Data type is integer and default value is 0.
+ * @since_tizen 3.0
+ * @see media_streamer_node_get_params
+ */
+#define MEDIA_STREAMER_PARAM_CAMERA_ID "camera-id"
+
+/**
+ * @brief Definition for capture parameter of source node.
+ * @details Width for camera size to capture.
+ *          Data type is integer and default value is 1600.
+ * @since_tizen 3.0
+ * @see media_streamer_node_get_params
+ */
+#define MEDIA_STREAMER_PARAM_CAPTURE_WIDTH "capture-width"
+
+/**
+ * @brief Definition for capture parameter of source node.
+ * @details Height for camera size to capture.
+ *          Data type is integer and default value is 1200.
+ * @since_tizen 3.0
+ * @see media_streamer_node_get_params
+ */
+#define MEDIA_STREAMER_PARAM_CAPTURE_HEIGHT "capture-height"
+
+/**
+ * @brief Definition for is-live parameter of source node.
+ * @details Whether to act as a live source.
+ *          Data type is boolean and default value is false.
+ * @since_tizen 3.0
+ * @see media_streamer_node_get_params
+ */
+#define MEDIA_STREAMER_PARAM_IS_LIVE_STREAM "is-live"
+
+/**
+ * @brief Definition for uri parameter of source node.
+ * @details Uri to read from
+ *          Data type is string.
+ * @since_tizen 3.0
+ * @see media_streamer_node_get_params
+ */
+#define MEDIA_STREAMER_PARAM_URI "uri"
+
+/**
+ * @brief Definition for user-agent parameter of source node
+ * @details Value of the User-Agent HTTP request header field.
+ *          Data type is string.
+ * @since_tizen 3.0
+ * @see media_streamer_node_get_params
+ */
+#define MEDIA_STREAMER_PARAM_USER_AGENT "user-agent"
+
+/**
+ * @brief Definition for stream type parameter of source node
+ * @details The type of the push data stream.
+ *          0:stream, 1:seekable, 2:random-access (default:0)
+ * @since_tizen 3.0
+ * @see media_streamer_node_get_params
+ */
+#define MEDIA_STREAMER_PARAM_STREAM_TYPE "stream-type"
+
+/**
+ * @brief Definition for port parameter of source or sink node
+ * @details The port to receive the packets from.
+ *          Data type is integer and default value is 5004.
+ * @since_tizen 3.0
+ * @see media_streamer_node_get_params
+ */
+#define MEDIA_STREAMER_PARAM_PORT "port"
+
+/**
+ * @brief Definition for video port parameter of source node
+ * @details The port to receive the video packets from.
+ *          Data type is integer.
+ * @since_tizen 3.0
+ * @see media_streamer_node_get_params
+ */
+#define MEDIA_STREAMER_PARAM_VIDEO_IN_PORT "video_in_port"
+
+/**
+ * @brief Definition for audio port parameter of source node
+ * @details The port to receive the audio packets from.
+ *          Data type is integer.
+ * @since_tizen 3.0
+ * @see media_streamer_node_get_params
+ */
+#define MEDIA_STREAMER_PARAM_AUDIO_IN_PORT "audio_in_port"
+
+/**
+ * @brief Definition for video port parameter of sink node
+ * @details The port to send the video packets to.
+ *          Data type is integer.
+ * @since_tizen 3.0
+ * @see media_streamer_node_get_params
+ */
+#define MEDIA_STREAMER_PARAM_VIDEO_OUT_PORT "video_out_port"
+
+/**
+ * @brief Definition for audio port parameter of sink node
+ * @details The port to send the audio packets to.
+ *          Data type is integer.
+ * @since_tizen 3.0
+ * @see media_streamer_node_get_params
+ */
+#define MEDIA_STREAMER_PARAM_AUDIO_OUT_PORT "audio_out_port"
+
+/**
+ * @brief Definition for IP address parameter of source node
+ * @details IP address to send/receive packets for.
+ *          Data type is string and default value is "0.0.0.0".
+ * @since_tizen 3.0
+ * @see media_streamer_node_get_params
+ */
+#define MEDIA_STREAMER_PARAM_IP_ADDRESS "address"
+
+/**
+ * @brief Definition for audio device name parameter of source or sink node
+ * @details ALSA device, as defined in an asound configuration file.
+ *          ex) "hw:0,0", "hw:0,1"
+ *          Data type is string and default value is "default".
+ * @since_tizen 3.0
+ * @see media_streamer_node_get_params
+ */
+#define MEDIA_STREAMER_PARAM_AUDIO_DEVICE "audio_device"
+
+/**
+ * @brief Definition for sync parameter of sink node
+ * @details Synchronize on the clock
+ *          Data type is boolean and default value is true.
+ * @since_tizen 3.0
+ * @see media_streamer_node_get_params
+ */
+#define MEDIA_STREAMER_PARAM_CLOCK_SYNCHRONIZED "sync"
+
+/**
+ * @brief Definition for rotate parameter of sink node
+ * @details Rotate angle of display output.
+ *          0:none/1:rotate 90 degree/2:rotate 180 degree/3:rotate 270 degree
+ *          Default value is 3(rotate 270 degree).
+ * @since_tizen 3.0
+ * @see media_streamer_node_get_params
+ */
+#define MEDIA_STREAMER_PARAM_ROTATE "rotate"
+
+/**
+ * @brief Definition for flip parameter of sink node
+ * @details Flip for display.
+ *          0:none, 1:horizontal, 2:vertical, 3:both
+ *          Default value is 0.
+ * @since_tizen 3.0
+ * @see media_streamer_node_get_params
+ */
+#define MEDIA_STREAMER_PARAM_FLIP "flip"
+
+/**
+ * @brief Definition for display geometry method parameter of sink node
+ * @details Geometrical method for display.
+ *          0:Letter box
+ *          1:Original size
+ *          2:Full-screen
+ *          3:Cropped full screen
+ *          4:Original size if surface size is larger than video size(width/height),
+ *            or Letter box if video size(width/height) is larger than surface size.
+ *          5:Custom ROI
+ *          Default value is 0(Letter box).
+ * @since_tizen 3.0
+ * @see media_streamer_node_get_params
+ */
+#define MEDIA_STREAMER_PARAM_DISPLAY_GEOMETRY_METHOD "display-geometry-method"
+
+/**
+ * @brief Definition for visible parameter of sink node
+ * @details Draws screen or blacks out.
+ *          Data type is boolean and default value is true(visible).
+ * @since_tizen 3.0
+ * @see media_streamer_node_get_params
+ */
+#define MEDIA_STREAMER_PARAM_VISIBLE "visible"
+
+/**
+ * @brief Definition for host parameter of sink node
+ * @details The host/IP/Multicast group to send the packets to.
+ *          Data type is string and default value is "localhost".
+ * @since_tizen 3.0
+ * @see media_streamer_node_get_params
+ */
+#define MEDIA_STREAMER_PARAM_HOST "host"
+
+
+/**
  * @brief Called when error occurs in media streamer.
+ * @details Following error codes can be delivered.
+ *          #MEDIA_STREAMER_ERROR_INVALID_OPERATION,
+ *          #MEDIA_STREAMER_ERROR_FILE_NO_SPACE_ON_DEVICE,
+ *          #MEDIA_STREAMER_ERROR_NOT_SUPPORTED,
+ *          #MEDIA_STREAMER_ERROR_CONNECTION_FAILED,
+ *          #MEDIA_STREAMER_ERROR_RESOURCE_CONFLICT
  * @since_tizen 3.0
  * @param [in] streamer    Media streamer handle
  * @param [in] error       The error that occurred in media steamer
@@ -188,10 +377,10 @@ typedef void (*media_streamer_error_cb)(media_streamer_h streamer,
                                         void *user_data);
 
 /**
- * @brief Called when media streamer state was changed.
+ * @brief Called when media streamer state is changed.
  * @since_tizen 3.0
  * @param [in] streamer            Media streamer handle
- * @param [in] previous_state      The previous state of the media steamer
+ * @param [in] previous_state      The previous state of the media streamer
  * @param [in] current_state       The current state of media streamer
  * @param [in] user_data           The user data passed from the code where
  *                                 media_streamer_set_state_changed_cb() was invoked
@@ -210,12 +399,12 @@ typedef void (*media_streamer_state_changed_cb)(media_streamer_h streamer,
  * @details This callback will be invoked when the buffer level drops below the threshold of max size
  *          or no free space in custom source buffer.
  * @since_tizen 3.0
- * @remarks Callback can be applied only for MEDIA_STREAMER_SRC_TYPE_CUSTOM source type
+ * @remarks Callback can be applied only for MEDIA_STREAMER_NODE_SRC_TYPE_CUSTOM source type
  * @param [in] node      Media streamer source node handle
  * @param [in] user_data The user data passed from the callback registration function
  * @see media_streamer_src_set_buffer_status_cb()
- * @see media_streamer_node_get_param_list()
- * @see media_streamer_node_set_params()
+ * @see media_streamer_node_get_param()
+ * @see media_streamer_node_set_param()
  */
 typedef void (*media_streamer_custom_buffer_status_cb)(media_streamer_node_h node,
                                                        media_streamer_custom_buffer_status_e status,
@@ -223,14 +412,14 @@ typedef void (*media_streamer_custom_buffer_status_cb)(media_streamer_node_h nod
 
 /**
  * @brief Called when new data is available from custom sink.
- * @details This callback can be applied only to MEDIA_STREAMER_SINK_TYPE_CUSTOM sink type
+ * @details This callback can be applied only to MEDIA_STREAMER_NODE_SINK_TYPE_CUSTOM sink type
  * @since_tizen 3.0
  * @param [in] node      Media streamer sink node handle
  * @param [in] user_data The user data passed from the code where
  *                       media_streamer_sink_set_data_ready_cb() was invoked
  *                       This data will be accessible from @a media_streamer_sink_data_ready_cb
  * @pre media_streamer_sink_set_data_ready_cb()
- * @see MEDIA_STREAMER_SINK_TYPE_CUSTOM
+ * @see MEDIA_STREAMER_NODE_SINK_TYPE_CUSTOM
  * @see media_streamer_sink_set_data_ready_cb()
  * @see media_streamer_sink_unset_data_ready_cb()
  */
@@ -239,14 +428,14 @@ typedef void (*media_streamer_sink_data_ready_cb)(media_streamer_node_h node,
 
 /**
  * @brief  Called when the end-of-stream has been reached.
- * @details This callback can be applied only to MEDIA_STREAMER_SINK_TYPE_CUSTOM sink type
+ * @details This callback can be applied only to MEDIA_STREAMER_NODE_SINK_TYPE_CUSTOM sink type
  * @since_tizen 3.0
  * @param [in] node      Media streamer sink node handle
  * @param [in] user_data The user data passed from the code where
  *                       media_streamer_sink_set_eos_cb() was invoked
  *                       This data will be accessible from @a media_streamer_sink_eos_cb
  * @pre media_streamer_sink_set_eos_cb()
- * @see MEDIA_STREAMER_SINK_TYPE_CUSTOM
+ * @see MEDIA_STREAMER_NODE_SINK_TYPE_CUSTOM
  * @see media_streamer_sink_set_eos_cb()
  * @see media_streamer_sink_unset_eos_cb()
  */
@@ -254,7 +443,13 @@ typedef void (*media_streamer_sink_eos_cb)(media_streamer_node_h node,
                                            void *user_data);
 
 /**
- * @brief Register a error callback function to be invoked when an error occurs.
+ * @brief Registers a error callback function to be invoked when an error occurs.
+ * @details Following error codes can be delivered by error callback.
+ *          #MEDIA_STREAMER_ERROR_INVALID_OPERATION,
+ *          #MEDIA_STREAMER_ERROR_FILE_NO_SPACE_ON_DEVICE,
+ *          #MEDIA_STREAMER_ERROR_NOT_SUPPORTED,
+ *          #MEDIA_STREAMER_ERROR_CONNECTION_FAILED,
+ *          #MEDIA_STREAMER_ERROR_RESOURCE_CONFLICT
  * @since_tizen 3.0
  * @param [in] streamer  Media streamer handle
  * @param [in] callback  Callback function pointer
@@ -264,7 +459,6 @@ typedef void (*media_streamer_sink_eos_cb)(media_streamer_node_h node,
  * @return @c 0 on success,
  *         otherwise a negative error value
  * @retval #MEDIA_STREAMER_ERROR_NONE Successful
- * @retval #MEDIA_STREAMER_ERROR_INVALID_STATE Invalid state
  * @retval #MEDIA_STREAMER_ERROR_INVALID_PARAMETER Invalid parameter
  * @retval #MEDIA_STREAMER_ERROR_INVALID_OPERATION Invalid operation
  * @pre Create a media streamer handle by calling media_streamer_create() function
@@ -290,7 +484,7 @@ int media_streamer_set_error_cb(media_streamer_h streamer,
 int media_streamer_unset_error_cb(media_streamer_h streamer);
 
 /**
- * @brief Register a callback that will be triggered after media streamer state was changed.
+ * @brief Registers a callback that will be triggered after media streamer state is changed.
  * @since_tizen 3.0
  * @param [in] streamer  Media streamer handle
  * @param [in] callback  Callback function pointer
@@ -300,7 +494,6 @@ int media_streamer_unset_error_cb(media_streamer_h streamer);
  * @return @c 0 on success,
  *         otherwise a negative error value
  * @retval #MEDIA_STREAMER_ERROR_NONE Successful
- * @retval #MEDIA_STREAMER_ERROR_INVALID_STATE Invalid state
  * @retval #MEDIA_STREAMER_ERROR_INVALID_PARAMETER Invalid parameter
  * @retval #MEDIA_STREAMER_ERROR_INVALID_OPERATION Invalid operation
  * @pre Create a media streamer handle by calling media_streamer_create() function
@@ -327,7 +520,7 @@ int media_streamer_unset_state_change_cb(media_streamer_h streamer);
 
 /**
  * @brief Registers a callback function to be invoked when buffer underrun or overflow is occurred.
- * @details This function can be called only for MEDIA_STREAMER_SRC_TYPE_CUSTOM source type
+ * @details This function can be called only for MEDIA_STREAMER_NODE_SRC_TYPE_CUSTOM source type
  * @since_tizen 3.0
  * @remarks This API is used for media stream playback only.
  * @param [in] source    Media streamer source node handle
@@ -338,10 +531,9 @@ int media_streamer_unset_state_change_cb(media_streamer_h streamer);
  * @return @c 0 on success,
  *                otherwise a negative error value
  * @retval #MEDIA_STREAMER_ERROR_NONE Successful
- * @retval #MEDIA_STREAMER_ERROR_INVALID_STATE Invalid state
  * @retval #MEDIA_STREAMER_ERROR_INVALID_PARAMETER Invalid parameter
  * @retval #MEDIA_STREAMER_ERROR_INVALID_OPERATION Invalid operation
- * @pre Create a media streamer source node handle by calling media_streamer_src_create() function
+ * @pre Create a media streamer source node handle by calling media_streamer_node_create_src() function
  * @pre Add created media streamer source node to media streamer by calling media_streamer_node_add() function
  * @post media_streamer_custom_buffer_status_cb() will be invoked.
  * @see media_streamer_src_unset_buffer_status_cb()
@@ -365,8 +557,8 @@ int media_streamer_src_set_buffer_status_cb(media_streamer_node_h source,
 int media_streamer_src_unset_buffer_status_cb(media_streamer_node_h source);
 
 /**
- * @brief Register a callback function to be called when the custom sink is ready for data processing.
- * @details This function can be called only for MEDIA_STREAMER_SINK_TYPE_CUSTOM sink type
+ * @brief Registers a callback function to be called when the custom sink is ready for data processing.
+ * @details This function can be called only for MEDIA_STREAMER_NODE_SINK_TYPE_CUSTOM sink type
  * @since_tizen 3.0
  * @param [in] sink      Media streamer sink handle
  * @param [in] callback  Callback function pointer
@@ -376,10 +568,9 @@ int media_streamer_src_unset_buffer_status_cb(media_streamer_node_h source);
  * @return @c 0 on success,
  *         otherwise a negative error value
  * @retval #MEDIA_STREAMER_ERROR_NONE Successful
- * @retval #MEDIA_STREAMER_ERROR_INVALID_STATE Invalid state
  * @retval #MEDIA_STREAMER_ERROR_INVALID_PARAMETER Invalid parameter
  * @retval #MEDIA_STREAMER_ERROR_INVALID_OPERATION Invalid operation
- * @pre Create a media streamer sink handle by calling media_streamer_sink_create() function
+ * @pre Create a media streamer sink handle by calling media_streamer_node_create_sink() function
  * @pre Add created media streamer sink node to media streamer by calling media_streamer_node_add() function
  * @post media_streamer_sink_data_ready_cb() will be invoked.
  * @see media_streamer_sink_unset_data_ready_cb()
@@ -400,7 +591,7 @@ int media_streamer_sink_set_data_ready_cb(media_streamer_node_h sink,
  * @retval #MEDIA_STREAMER_ERROR_INVALID_OPERATION Invalid operation
  * @see media_streamer_sink_set_data_ready_cb()
  */
-int media_streamer_sink_unset_data_ready_cb(media_streamer_h streamer);
+int media_streamer_sink_unset_data_ready_cb(media_streamer_node_h sink);
 
 /**
  * @brief Registers a callback function to be called when custom sink detect the end-of-stream.
@@ -413,10 +604,9 @@ int media_streamer_sink_unset_data_ready_cb(media_streamer_h streamer);
  * @return @c 0 on success,
  *         otherwise a negative error value
  * @retval #MEDIA_STREAMER_ERROR_NONE Successful
- * @retval #MEDIA_STREAMER_ERROR_INVALID_STATE Invalid state
  * @retval #MEDIA_STREAMER_ERROR_INVALID_PARAMETER Invalid parameter
  * @retval #MEDIA_STREAMER_ERROR_INVALID_OPERATION Invalid operation
- * @pre Create a media streamer sink handle by calling media_streamer_sink_create() function
+ * @pre Create a media streamer sink handle by calling media_streamer_node_create_sink() function
  * @pre Add created media streamer sink node to media streamer by calling media_streamer_node_add() function
  * @post media_streamer_sink_eos_cb() will be invoked.
  * @see media_streamer_sink_unset_eos_cb()
@@ -437,7 +627,7 @@ int media_streamer_sink_set_eos_cb(media_streamer_node_h sink,
  * @retval #MEDIA_STREAMER_ERROR_INVALID_OPERATION Invalid operation
  * @see media_streamer_sink_set_eos_cb()
  */
-int media_streamer_sink_unset_eos_cb(media_streamer_h streamer);
+int media_streamer_sink_unset_eos_cb(media_streamer_node_h sink);
 
 /**
  * @brief Creates an instance of media streamer and
@@ -468,7 +658,7 @@ int media_streamer_create(media_streamer_h *streamer);
  * @pre        The media streamer state must be set to #MEDIA_STREAMER_STATE_IDLE
  *      by calling media_streamer_create() or media_streamer_unprepare().
  * @pre At least one src and one sink should be added and linked in the streamer
- *      by calling media_streamer_src_create(), media_streamer_sink_create() and media_streamer_node_link().
+ *      by calling media_streamer_node_create_src(), media_streamer_node_create_sink() and media_streamer_node_link().
  * @post The media streamer state will be #MEDIA_STREANER_STATE_READY.
  * @see media_streamer_unprepare()
  * @see media_streamer_create()
@@ -494,7 +684,7 @@ int media_streamer_unprepare(media_streamer_h streamer);
 
 /**
  * @brief Sets media streamer state to MEDIA_STREAMER_STATE_PLAYING.
- * @details start running the current streamer, or resumes it if paused.
+ * @details Start running the current streamer, or resumes it if paused.
  * @since_tizen 3.0
  * @param [in] streamer     Media streamer handle
  * @return @c 0 on success,
@@ -513,7 +703,7 @@ int media_streamer_unprepare(media_streamer_h streamer);
 int media_streamer_play(media_streamer_h streamer);
 
 /**
- * @brief Pause the media streamer.
+ * @brief Pauses the media streamer.
  * @since_tizen 3.0
  * @param [in] streamer     Media streamer handle
  * @return @c 0 on success,
@@ -539,11 +729,11 @@ int media_streamer_pause(media_streamer_h streamer);
  * @retval #MEDIA_STREAMER_ERROR_INVALID_STATE Invalid state
  * @retval #MEDIA_STREAMER_ERROR_INVALID_PARAMETER Invalid parameter
  * @retval #MEDIA_STREAMER_ERROR_INVALID_OPERATION Invalid operation
- * @pre The media streamer state must be set to #MEDIA_STREAMER_STATE_PLAYING by calling media_streamer_start() or
+ * @pre The media streamer state must be set to #MEDIA_STREAMER_STATE_PLAYING by calling media_streamer_play() or
  *      set to #MEDIA_STREAMER_STATE_PAUSED by calling media_streamer_pause().
  * @post The media streamer state will be #MEDIA_STREAMER_STATE_READY.
  * @see media_streamer_create()
- * @see media_streamer_start()
+ * @see media_streamer_play()
  * @see media_streamer_pause()
  */
 int media_streamer_stop(media_streamer_h streamer);
@@ -551,6 +741,11 @@ int media_streamer_stop(media_streamer_h streamer);
 /**
  * @brief Destroys media streamer.
  * @since_tizen 3.0
+ * @remark Nodes in streamer will be removed automatically.
+ *         Don't need to remove nodes by calling media_streamer_node_remove().
+ *         If you want to change the node without destroying streamer handle,
+ *         you can call the media_streamer_node_remove() function
+ *         after setting the streamer state to MEDIA_STREAMER_STATE_IDLE state.
  * @param [in] streamer     Media streamer handle
  * @return @c 0 on success,
  *         otherwise a negative error value
@@ -572,7 +767,6 @@ int media_streamer_destroy(media_streamer_h streamer);
  * @return @c 0 on success,
  *         otherwise a negative error value
  * @retval #MEDIA_STREAMER_ERROR_NONE    Successful
- * @retval #MEDIA_STREAMER_ERROR_INVALID_STATE Invalid state
  * @retval #MEDIA_STREAMER_ERROR_INVALID_PARAMETER Invalid parameter
  * @retval #MEDIA_STREAMER_ERROR_INVALID_OPERATION Invalid operation
  * @pre Create a media streamer handle by calling media_streamer_create() function
@@ -584,18 +778,12 @@ int media_streamer_get_state(media_streamer_h streamer,
 /**
  * @brief Creates media streamer source node.
  * @since_tizen 3.0
- * @privlevel public
- * @privilege http://tizen.org/privilege/mediastorage
- *            http://tizen.org/privilege/externalstorage
- *            http://tizen.org/privilege/internet
- *            http://tizen.org/privilege/camera
- *            http://tizen.org/privilege/recorder
  * @remarks The mediastorage privilege(http://tizen.org/privilege/mediastorage) should be added if any video/audio files are used to play located in the internal storage.
- * @remarks The externalstorage privilege(http://tizen.org/privilege/externalstorage) should be added if any video/audio files are used to play located in the external storage.
- * @remarks The internet privilege(http://tizen.org/privilege/internet) should be added if any URIs are used to play from network.
- * @remarks The camera privilege(http://tizen.org/privilege/camera) should be added if the src node handle the camera device.
- * @remarks The recorder privilege(http://tizen.org/privilege/recorder) should be added if the src node handle the recorder device.
- * @remarks You can release @a source node using media_streamer_node_destroy() function
+ *          The externalstorage privilege(http://tizen.org/privilege/externalstorage) should be added if any video/audio files are used to play located in the external storage.
+ *          The internet privilege(http://tizen.org/privilege/internet) should be added if any URIs are used to play from network.
+ *          The camera privilege(http://tizen.org/privilege/camera) should be added if the src node handle the camera device.
+ *          The recorder privilege(http://tizen.org/privilege/recorder) should be added if the src node handle the recorder device.
+ *          You can release @a source node using media_streamer_node_destroy() function.
  * @param [in]  type     Media streamer source node type
  * @param [out] src      Media streamer source node handle
  * @return @c 0 on success,
@@ -604,16 +792,16 @@ int media_streamer_get_state(media_streamer_h streamer,
  * @retval #MEDIA_STREAMER_ERROR_INVALID_PARAMETER Invalid parameter
  * @retval #MEDIA_STREAMER_ERROR_INVALID_OPERATION Invalid operation
  * @retval #MEDIA_STREAMER_ERROR_PERMISSION_DENIED Permission denied
- * @retval #MEDIA_STREAMER_ERROR_FEATURE_NOT_SUPPORTED_ON_DEVICE Not support on device
- * @see #media_streamer_src_type_e
+ * @retval #MEDIA_STREAMER_ERROR_NOT_SUPPORTED Not supported
+ * @see #media_streamer_node_src_type_e
  * @see media_streamer_node_destroy()
  */
-int media_streamer_src_create(media_streamer_src_type_e type,
+int media_streamer_node_create_src(media_streamer_node_src_type_e type,
                               media_streamer_node_h *src);
 
 /**
  * @brief Pushes packet into custom source node.
- * @details This function can be called only for MEDIA_STREAMER_SRC_TYPE_CUSTOM.
+ * @details This function can be called only for MEDIA_STREAMER_NODE_SRC_TYPE_CUSTOM.
  * @since_tizen 3.0
  * @param [in] src       Media streamer source node handle
  * @param [in] packet    Media packet handle
@@ -624,25 +812,20 @@ int media_streamer_src_create(media_streamer_src_type_e type,
  * @retval #MEDIA_STREAMER_ERROR_INVALID_PARAMETER Invalid parameter
  * @retval #MEDIA_STREAMER_ERROR_INVALID_OPERATION Invalid operation
  * @retval #MEDIA_STREAMER_ERROR_PERMISSION_DENIED Permission denied
- * @pre Create a source node handle by calling media_streamer_src_create() function
+ * @pre Create a source node handle by calling media_streamer_node_create_src() function
  * @pre        The media streamer state must be set to #MEDIA_STREAMER_STATE_IDLE at least.
  * @see #media_packet_h
  */
-int media_streamer_push_packet(media_streamer_node_h src,
+int media_streamer_node_push_packet(media_streamer_node_h src,
                                media_packet_h packet);
 
 /**
  * @brief Creates media streamer sink node.
- * @details This function can be called only for MEDIA_STREAMER_SINK_TYPE_CUSTOM
  * @since_tizen 3.0
- * @privlevel public
- * @privilege http://tizen.org/privilege/mediastorage
- *            http://tizen.org/privilege/externalstorage
- *            http://tizen.org/privilege/internet
  * @remarks The mediastorage privilege(http://tizen.org/privilege/mediastorage) should be added if any video/audio files are written in the internal storage devices.
- * @remarks The externalstorage privilege(http://tizen.org/privilege/externalstorage) should be added if any video/audio files are written in the external storage devices.
- * @remarks The internet privilege(http://tizen.org/privilege/internet) should be added if any URIs are used to transmit the output data.
- * @remarks You can release @a sink node using media_streamer_node_destroy()
+ *          The externalstorage privilege(http://tizen.org/privilege/externalstorage) should be added if any video/audio files are written in the external storage devices.
+ *          The internet privilege(http://tizen.org/privilege/internet) should be added if any URIs are used to transmit the output data.
+ *          You can release @a sink node using media_streamer_node_destroy()
  * @param [in]  type     Type of sink node to be created
  * @param [out] sink     Media streamer sink node handle
  * @return @c 0 on success,
@@ -651,16 +834,16 @@ int media_streamer_push_packet(media_streamer_node_h src,
  * @retval #MEDIA_STREAMER_ERROR_INVALID_PARAMETER Invalid parameter
  * @retval #MEDIA_STREAMER_ERROR_INVALID_OPERATION Invalid operation
  * @retval #MEDIA_STREAMER_ERROR_PERMISSION_DENIED Permission denied
- * @retval #MEDIA_STREAMER_ERROR_FEATURE_NOT_SUPPORTED_ON_DEVICE Not support on device
- * @see #media_streamer_sink_type_e
+ * @retval #MEDIA_STREAMER_ERROR_NOT_SUPPORTED Not supported
+ * @see #media_streamer_node_sink_type_e
  * @see media_streamer_node_destroy()
  */
-int media_streamer_sink_create(media_streamer_sink_type_e type,
+int media_streamer_node_create_sink(media_streamer_node_sink_type_e type,
                                media_streamer_node_h *sink);
 
 /**
  * @brief Pulls packet from custom sink node.
- * @details This function can be called only for MEDIA_STREAMER_SINK_TYPE_CUSTOM
+ * @details This function can be called only for MEDIA_STREAMER_NODE_SINK_TYPE_CUSTOM
  * @since_tizen 3.0
  * @param [in] sink      Media streamer sink node handle
  * @param [out] packet   Media packet handle
@@ -670,20 +853,22 @@ int media_streamer_sink_create(media_streamer_sink_type_e type,
  * @retval #MEDIA_STREAMER_ERROR_INVALID_STATE Invalid state
  * @retval #MEDIA_STREAMER_ERROR_INVALID_PARAMETER Invalid parameter
  * @retval #MEDIA_STREAMER_ERROR_INVALID_OPERATION Invalid operation
- * @pre Create a sink node handle by calling media_streamer_sink_create() function
+ * @pre Create a sink node handle by calling media_streamer_node_create_sink() function
  * @pre Set media_streamer_data_ready_cb by calling media_streamer_set_data_ready_cb() function.
  * @see #media_packet_h
- * @see media_streamer_sink_create()
+ * @see media_streamer_node_create_sink()
  */
-int media_streamer_pull_packet(media_streamer_node_h sink,
+int media_streamer_node_pull_packet(media_streamer_node_h sink,
                                media_packet_h *packet);
 
 /**
- * @brief Creates media streamer node except src and sink.
+ * @brief Creates media streamer node except MEDIA_STREAMER_NODE_TYPE_SRC and MEDIA_STREAMER_NODE_TYPE_SINK.
  * @details Creates node specific @a type with specific format of input
  *          and output data.
  * @since_tizen 3.0
- * @remarks You can release @a node using media_streamer_node_destroy() function
+ * @remarks The node type should not be MEDIA_STREAMER_NODE_TYPE_SRC and MEDIA_STREAMER_NODE_TYPE_SINK.
+ *          To create src/sink type node, media_streamer_node_create_src()/media_streamer_node_create_sink() should be called.
+ *          You can release @a node using media_streamer_node_destroy() function
  * @param [in]  type      Created node type
  * @param [in]  in_fmt    Media format handle for input data
  * @param [in]  out_fmt   Media format handle for output data
@@ -717,8 +902,8 @@ int media_streamer_node_create(media_streamer_node_type_e type,
  * @pre Create node handle by calling media_streamer_node_create() function
  * @see media_streamer_create()
  * @see media_streamer_node_create()
- * @see media_streamer_src_create()
- * @see media_streamer_sink_create()
+ * @see media_streamer_node_create_src()
+ * @see media_streamer_node_create_sink()
  */
 int media_streamer_node_add(media_streamer_h streamer,
                             media_streamer_node_h node);
@@ -736,16 +921,17 @@ int media_streamer_node_add(media_streamer_h streamer,
  * @pre Create node handle by calling media_streamer_node_create() function
  * @pre If the node was added to media streamer, it have to be removed by calling media_streamer_node_remove() function
  * @see media_streamer_node_create()
- * @see media_streamer_src_create()
- * @see media_streamer_sink_create()
+ * @see media_streamer_node_create_src()
+ * @see media_streamer_node_create_sink()
  * @see media_streamer_node_remove()
  */
 int media_streamer_node_destroy(media_streamer_node_h node);
 
 /**
- * @brief Remove media streamer node from streamer.
+ * @brief Removes media streamer node from streamer.
  * @since_tizen 3.0
- * @remarks If the node is linked, it will be unlinked before removing.
+ * @remarks To remove node without error posting, the state of streamer should be MEDIA_STREAMER_STATE_IDLE.
+ *          If the node is linked, it will be unlinked before removing.
  * @param [in] streamer    Media streamer handle
  * @param [in] node        Media streamer node handle
  * @return @c 0 on success,
@@ -761,9 +947,42 @@ int media_streamer_node_remove(media_streamer_h streamer,
                                media_streamer_node_h node);
 
 /**
- * @brief Sets media format for media streamer node.
+ * @brief Links two media streamer nodes.
+ * @since_tizen 3.0
+ * @remark Pads are node's input and output, where you can connect other nodes.
+ *         (src_node) - (sink_node)
+ *         src_node and sink_node is determined relatively.
+ *         In case of (A)-(B)-(C),
+ *         (B) can be sink_node with (A) or (B) can be src_node with (C).
+ *         However, src type node is always src node and sink type node is always sink node.
+ *         (A) is src node and can not be sink node at all.
+ *         (C) is sink node and can not be src node at all.
+ * @param [in] src_node      Media streamer node handle
+ * @param [in] src_pad_name  The name of the source pad of the source node
+ * @param [in] dest_node     The destination media streamer node handle
+ * @param [in] sink_pad_name The name of the sink pad of the destination node
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #MEDIA_STREAMER_ERROR_NONE Successful
+ * @retval #MEDIA_STREAMER_ERROR_INVALID_STATE Invalid state
+ * @retval #MEDIA_STREAMER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIA_STREAMER_ERROR_INVALID_OPERATION Invalid operation
+ * @pre Create a source node and a destination node handles
+ *      by calling media_streamer_node_create() function
+ *      and add the nodes into streamer by calling media_streamer_node_add() function.
+ * @see media_streamer_node_create()
+ * @see media_streamer_node_add()
+ */
+int media_streamer_node_link(media_streamer_node_h src_node,
+                             const char *src_pad_name,
+                             media_streamer_node_h dest_node,
+                             const char *sink_pad_name);
+
+/**
+ * @brief Sets media format for pad of media streamer node.
  * @since_tizen 3.0
  * @param [in] node        Media streamer node handle
+ * @param [in] pad_name    Pad name
  * @param [in] fmt         Media format handle
  * @return @c 0 on success,
  *         otherwise a negative error value
@@ -771,16 +990,19 @@ int media_streamer_node_remove(media_streamer_h streamer,
  * @retval #MEDIA_STREAMER_ERROR_INVALID_STATE Invalid state
  * @retval #MEDIA_STREAMER_ERROR_INVALID_PARAMETER Invalid parameter
  * @retval #MEDIA_STREAMER_ERROR_INVALID_OPERATION Invalid operation
- * @pre Create node handle by calling media_streamer_node_create() function
+ * @pre Create a node handle by calling media_streamer_node_createxxx() function
+ * @pre Get pad name by calling media_streamer_node_get_pad_name() function
  * @see #media_format_h
  */
-int media_streamer_node_set_format(media_streamer_node_h node,
+int media_streamer_node_set_pad_format(media_streamer_node_h node,
+                                   const char *pad_name,
                                    media_format_h fmt);
 
 /**
- * @brief Gets media format for media streamer node.
+ * @brief Gets media format for pad of media streamer node.
  * @since_tizen 3.0
  * @param [in] node        Media streamer node handle
+ * @param [in] pad_name    Pad name
  * @param [out] fmt        Media format handle
  * @return @c 0 on success,
  *         otherwise a negative error value
@@ -788,80 +1010,87 @@ int media_streamer_node_set_format(media_streamer_node_h node,
  * @retval #MEDIA_STREAMER_ERROR_INVALID_STATE Invalid state
  * @retval #MEDIA_STREAMER_ERROR_INVALID_PARAMETER Invalid parameter
  * @retval #MEDIA_STREAMER_ERROR_INVALID_OPERATION Invalid operation
- * @pre Create a source node handle by calling media_streamer_node_create() function
+ * @pre Create a node handle by calling media_streamer_node_createxxx() function
+ * @pre Get pad name by calling media_streamer_node_get_pad_name() function
  * @see #media_format_h
  */
-int media_streamer_node_get_format(media_streamer_node_h node,
+int media_streamer_node_get_pad_format(media_streamer_node_h node,
+                                   const char *pad_name,
                                    media_format_h *fmt);
 
 /**
- * @brief Links two media streamer nodes.
+ * @brief Gets name of node pads.
  * @since_tizen 3.0
- * @param [in] src_node   Media streamer node handle
- * @param [in] src_pad    The name of the source pad of the source node
- * @param [in] dest_node  The destination media streamer node handle
- * @param [in] sink_pad   The name of the sink pad of the destination node
+ * @remark After using the src_pad_name and sink_pad_name, it have to be free.
+ *         src_pad_name or sink_pad_name can be null accoring to the node type.
+ *         In case of src type node, sink_pad_name will be null.
+ *         In case of sink type node, src_pad_name will be null.
+ * @param [in]  node            Media streamer node handle
+ * @param [out] src_pad_name    Array of source pad name
+ * @param [out] src_pad_num     The number of source pads
+ * @param [out] sink_pad_name   Array of sink pad name
+ * @param [out] sink_pad_num    The number of sink pads
  * @return @c 0 on success,
  *         otherwise a negative error value
  * @retval #MEDIA_STREAMER_ERROR_NONE Successful
- * @retval #MEDIA_STREAMER_ERROR_INVALID_STATE Invalid state
  * @retval #MEDIA_STREAMER_ERROR_INVALID_PARAMETER Invalid parameter
  * @retval #MEDIA_STREAMER_ERROR_INVALID_OPERATION Invalid operation
- * @pre Create a source node and a destination node handles
- *      by calling media_streamer_node_create() function
- *      and add the nodes into streamer by calling media_streamer_node_add() function.
+ * @pre Create a node handle by calling media_streamer_node_createxxx() function
  * @see media_streamer_node_create()
- * @see media_streamer_node_add()
+ * @see media_streamer_node_create_src()
+ * @see media_streamer_node_create_sink()
  */
-int media_streamer_node_link(media_streamer_node_h src_node,
-                             const char *src_pad,
-                             media_streamer_node_h dest_node,
-                             const char *sink_pad);
+int media_streamer_node_get_pad_name(media_streamer_node_h node,
+                                       char ***src_pad_name,
+                                       int *src_pad_num,
+                                       char ***sink_pad_name,
+                                       int *sink_pad_num);
+
 
 /**
- * @brief Gets formats of node pads.
+ * @brief Sets parameters of node.
+ * @details Many parameters can be set at one time all together by using bundle.
  * @since_tizen 3.0
- * @remark After using the src_fmt and sink_fmt, it have to be free
- * @param [in]  node      Media streamer node handle
- * @param [out] src_fmt    Array of source pad formats
- * @param [out] sink_fmt   Array of sink pad formats
+ * @param [in] node        Media streamer node handle
+ * @param [in] param_list  Key value array of media streamer node parameters
  * @return @c 0 on success,
  *         otherwise a negative error value
  * @retval #MEDIA_STREAMER_ERROR_NONE Successful
  * @retval #MEDIA_STREAMER_ERROR_INVALID_STATE Invalid state
  * @retval #MEDIA_STREAMER_ERROR_INVALID_PARAMETER Invalid parameter
  * @retval #MEDIA_STREAMER_ERROR_INVALID_OPERATION Invalid operation
- * @pre Create a node handle by calling media_streamer_node_create() function
+ * @pre Create a node handle by calling media_streamer_node_createXXX() function.
+ * @pre Get param list to set by calling media_streamer_node_get_params() function.
  * @see media_streamer_node_create()
- * @see media_streamer_src_create()
- * @see media_streamer_sink_create()
+ * @see media_streamer_node_create_src()
+ * @see media_streamer_node_create_sink()
+ * @see media_streamer_node_get_params()
  */
-int media_streamer_node_get_pad_format(media_streamer_node_h node,
-                                       char **src_fmt,
-                                       char **sink_fmt);
-
+int media_streamer_node_set_params(media_streamer_node_h node,
+                                   bundle *param_list);
 /**
- * @brief Sets parameters of node.
- * @details Many parameters can be set at one time all together by using bundle.
+ * @brief Gets node parameter list.
  * @since_tizen 3.0
- * @param [in] node        Media streamer node handle
- * @param [in] param_list  Key value array of media streamer node parameters
+ * @remark After using param_list, it have to be free by calling bundle_free() in bundle.h
+ *         Refer to the "Parameter information of node" in this file to get info.
+ * @param [in]  node         Media streamer node handle
+ * @param [out] param_list   Key value array of media streamer node parameters
  * @return @c 0 on success,
  *         otherwise a negative error value
  * @retval #MEDIA_STREAMER_ERROR_NONE Successful
  * @retval #MEDIA_STREAMER_ERROR_INVALID_STATE Invalid state
  * @retval #MEDIA_STREAMER_ERROR_INVALID_PARAMETER Invalid parameter
  * @retval #MEDIA_STREAMER_ERROR_INVALID_OPERATION Invalid operation
- * @pre Create a node handle by calling media_streamer_node_create() function.
- * @pre Get param list to set by calling media_streamer_node_get_param_list() function.
+ * @pre Create a node handle by calling media_streamer_node_createXXX() function
+ * @post Set params which are needed to set by calling media_streamer_node_set_params() or media_streamer_node_set_param() function.
  * @see media_streamer_node_create()
  * @see media_streamer_src_create()
  * @see media_streamer_sink_create()
- * @see media_streamer_node_get_param_list()
- * @see media_streamer_node_set_single_param()
+ * @see media_streamer_node_set_params()
+ * @see media_streamer_node_set_param()
  */
-int media_streamer_node_set_params(media_streamer_node_h node,
-                                   bundle *param_list);
+int media_streamer_node_get_params(media_streamer_node_h node,
+                                   bundle **param_list);
 
 /**
  * @brief Sets single parameter of node.
@@ -876,38 +1105,41 @@ int media_streamer_node_set_params(media_streamer_node_h node,
  * @retval #MEDIA_STREAMER_ERROR_INVALID_STATE Invalid state
  * @retval #MEDIA_STREAMER_ERROR_INVALID_PARAMETER Invalid parameter
  * @retval #MEDIA_STREAMER_ERROR_INVALID_OPERATION Invalid operation
- * @pre Create a node handle by calling media_streamer_node_create() function.
- * @pre Get param list to set by calling media_streamer_node_get_param_list() function.
+ * @pre Create a node handle by calling media_streamer_node_createXXX() function.
+ * @pre Get param list to set by calling media_streamer_node_get_params() function.
  * @see media_streamer_node_create()
  * @see media_streamer_src_create()
  * @see media_streamer_sink_create()
- * @see media_streamer_node_get_param_list()
- * @see media_streamer_node_set_params()
+ * @see media_streamer_node_get_params()
+ * @see media_streamer_node_get_param()
  */
-int media_streamer_node_set_single_param(media_streamer_node_h node,
-                                         const char *param_name, const char *param_value);
+int media_streamer_node_set_param(media_streamer_node_h node,
+                                 const char *param_name, const char *param_value);
+
 
 /**
- * @brief Gets node parameter list.
+ * @brief Gets value of parameter.
+ * @details Gets parameter one by one without creating param bundle.
  * @since_tizen 3.0
- * @remark After using param_list, it have to be free by calling bundle_free() in bundle.h
- * @param [in]  node         Media streamer node handle
- * @param [out] param_list   Key value array of media streamer node parameters
+ * @param [in] node         Media streamer node handle
+ * @param [in] param_name   Param name of node
+ * @param [out] param_value Parm value of node
  * @return @c 0 on success,
  *         otherwise a negative error value
  * @retval #MEDIA_STREAMER_ERROR_NONE Successful
  * @retval #MEDIA_STREAMER_ERROR_INVALID_STATE Invalid state
  * @retval #MEDIA_STREAMER_ERROR_INVALID_PARAMETER Invalid parameter
  * @retval #MEDIA_STREAMER_ERROR_INVALID_OPERATION Invalid operation
- * @pre Create a node handle by calling media_streamer_node_create() function
- * @post Set params which are needed to set by calling media_streamer_node_set_params() function.
+ * @pre Create a node handle by calling media_streamer_node_createXXX() function.
+ * @pre Get param list to know the param name by calling media_streamer_node_get_params() function.
  * @see media_streamer_node_create()
  * @see media_streamer_src_create()
  * @see media_streamer_sink_create()
- * @see media_streamer_node_set_params()
+ * @see media_streamer_node_get_params()
+ * @see media_streamer_node_set_param()
  */
-int media_streamer_node_get_param_list(media_streamer_node_h node,
-                                       bundle **param_list);
+int media_streamer_node_get_param(media_streamer_node_h node,
+                                  const char *param_name, char **param_value);
 
 /**
  * @}
index 939fd4f..6df2fcd 100755 (executable)
@@ -52,7 +52,7 @@ GstElement *__ms_element_create(const char *plugin_name, const char *name);
  *
  * @since_tizen 3.0
  */
-GstElement *__ms_camera_element_create(const char *microphone_plugin_name);
+GstElement *__ms_camera_element_create(const char *camera_plugin_name);
 
 /**
  * @brief Creates encoder GstElement by mime type.
@@ -83,14 +83,28 @@ GstElement *__ms_audio_encoder_element_create(void);
 GstElement *__ms_rtp_element_create(media_streamer_node_s *ms_node);
 
 /**
- * @brief Parse param for RTP node type.
+ * @brief Find Udp elements into rtp container by name.
  *
  * @since_tizen 3.0
  */
-int __ms_rtp_set_param(
-                               media_streamer_node_s *node,
-                               const gchar *param_key,
-                               const gchar *param_value);
+gboolean __ms_get_rtp_elements(media_streamer_node_s *ms_node,
+                               GstElement **rtp_elem, GstElement **rtcp_elem, const gchar *elem_name);
+
+/**
+ * @brief Converts key-value property into needed GType
+ * and sets this property into GstElement.
+ *
+ * @since_tizen 3.0
+ */
+gboolean __ms_element_set_property(GstElement *src_element,
+                                   const gchar *key, const gchar *param_value);
+
+/**
+ * @brief Unlink all pads into GstElement.
+ *
+ * @since_tizen 3.0
+ */
+gboolean __ms_element_unlink(GstElement *src_element);
 
 /**
  * @brief Creates pipeline, bus and src/sink/topology bins.
@@ -104,7 +118,7 @@ int __ms_pipeline_create(media_streamer_s *ms_streamer);
  *
  * @since_tizen 3.0
  */
-int __ms_add_node_into_bin(media_streamer_s *ms_streamer,media_streamer_node_s *ms_node);
+int __ms_add_node_into_bin(media_streamer_s *ms_streamer, media_streamer_node_s *ms_node);
 
 /**
  * @brief Sets GstElement into state.
@@ -114,8 +128,29 @@ int __ms_add_node_into_bin(media_streamer_s *ms_streamer,media_streamer_node_s *
 int __ms_element_set_state(GstElement *gst_element, GstState gst_state);
 
 /**
+ * @brief Gets mediaformat from the GstElement's pad by pad name.
+ *
+ * @since_tizen 3.0
+ */
+media_format_h __ms_element_get_pad_fmt(GstElement *gst_element, const char* pad_name);
+
+/**
  * @brief Sets mediaformat into GstElement.
  *
  * @since_tizen 3.0
  */
 int __ms_element_set_fmt(media_streamer_node_s *node, media_format_h fmt);
+
+/**
+ * @brief Push the media packet buffer to the source element.
+ *
+ * @since_tizen 3.0
+ */
+int __ms_element_push_packet(GstElement *src_element, media_packet_h packet);
+
+/**
+ * @brief Pull the media packet buffer from sink element.
+ *
+ * @since_tizen 3.0
+ */
+int __ms_element_pull_packet(GstElement *sink_element, media_packet_h *packet);
index 8843ccf..c3143f7 100755 (executable)
@@ -22,8 +22,8 @@
  * @since_tizen 3.0
  */
 int __ms_node_create(media_streamer_node_s *node,
-                               media_format_h in_fmt,
-                               media_format_h out_fmt);
+                     media_format_h in_fmt,
+                     media_format_h out_fmt);
 
 /**
  * @brief Creates media streamer source node.
@@ -52,7 +52,7 @@ void __ms_node_destroy(void *data);
  * @since_tizen 3.0
  */
 void __ms_node_insert_into_table(GHashTable *nodes_table,
-                               media_streamer_node_s *ms_node);
+                                 media_streamer_node_s *ms_node);
 
 /**
  * @brief Remove media streamer node from nodes table.
@@ -60,20 +60,27 @@ void __ms_node_insert_into_table(GHashTable *nodes_table,
  * @since_tizen 3.0
  */
 int __ms_node_remove_from_table(GHashTable *nodes_table,
-                               media_streamer_node_s *ms_node);
+                                media_streamer_node_s *ms_node);
+
+/**
+ * @brief Auto link nodes if needed.
+ *
+ * @since_tizen 3.0
+ */
+int __ms_autoplug_prepare(media_streamer_s *ms_streamer);
 
 /**
  * @brief Reads node parameters from user's bundle object.
  *
  * @since_tizen 3.0
  */
-int __ms_node_read_params_from_bundle (media_streamer_node_s *node,
-               bundle *param_list);
+int __ms_node_read_params_from_bundle(media_streamer_node_s *node,
+                                      bundle *param_list);
 
 /**
  * @brief Writes GstElement properties into user's bundle object.
  *
  * @since_tizen 3.0
  */
-int __ms_node_write_params_into_bundle (media_streamer_node_s *node,
-               bundle *param_list);
+int __ms_node_write_params_into_bundle(media_streamer_node_s *node,
+                                       bundle *param_list);
index 67ecfc5..abd567e 100755 (executable)
@@ -39,16 +39,6 @@ typedef struct {
 } media_streamer_callback_s;
 
 /**
- * @brief Media Streamer source callbacks structure.
- *
- * @since_tizen 3.0
- */
-typedef struct {
-       media_streamer_callback_s enough_data_cb;
-       media_streamer_callback_s need_data_cb;
-} media_streamer_src_callbacks_s;
-
-/**
  * @brief Media Streamer sink callbacks structure.
  *
  * @since_tizen 3.0
@@ -89,10 +79,10 @@ typedef struct {
  *
  * @since_tizen 3.0
  */
-typedef int (*media_streamer_node_set_param)(
+typedef int (*ms_node_set_param)(
     struct media_streamer_node_s *node,
-    const gchar *param_key,
-    const gchar *param_value);
+    const char *param_key,
+    const char *param_value);
 
 /**
  * @brief Media Streamer node type handle.
@@ -105,7 +95,7 @@ typedef struct {
        media_streamer_s *parent_streamer;
        media_streamer_node_type_e type;
        int subtype;
-       media_streamer_node_set_param set_param;
+       ms_node_set_param set_param;
        void *callbacks_structure;
 } media_streamer_node_s;
 
index e0018c5..866e2ef 100755 (executable)
@@ -98,19 +98,24 @@ typedef struct __media_streamer_ini {
 } media_streamer_ini_t;
 
 /*Test elements*/
-#define DEFAULT_VIDEO_TEST_SOURCE                      "videotestsrc"
-#define DEFAULT_AUDIO_TEST_SOURCE                      "audiotestsrc"
+#define DEFAULT_VIDEO_TEST_SOURCE              "videotestsrc"
+#define DEFAULT_AUDIO_TEST_SOURCE              "audiotestsrc"
 #define DEFAULT_FAKE_SINK                              "fakesink"
 #define DEFAULT_QUEUE                                  "queue"
 
 /* setting default values if each value is not specified in .ini file */
 /* general */
-#define DEFAULT_GENERATE_DOT                           FALSE
-#define DEFAULT_AUDIO_SOURCE                           "alsasrc"
-#define DEFAULT_CAMERA_SOURCE                          "camerasrc"
-#define DEFAULT_VIDEO_SOURCE                           "ximagesrc"
+#define DEFAULT_GENERATE_DOT                   FALSE
+#define DEFAULT_AUDIO_SOURCE                   "alsasrc"
+#define DEFAULT_CAMERA_SOURCE                  "camerasrc"
+#define DEFAULT_VIDEO_SOURCE                   "ximagesrc"
+#define DEFAULT_APP_SOURCE                             "appsrc"
 #define DEFAULT_AUDIO_SINK                             "pulsesink"
 #define DEFAULT_VIDEO_SINK                             "autovideosink"
+#define DEFAULT_VIDEO_CONVERT                  "videoconvert"
+#define DEFAULT_AUDIO_CONVERT                  "audioconvert"
+#define DEFAULT_AUDIO_RESAMPLE                 "audioresample"
+#define DEFAULT_APP_SINK                               "appsink"
 
 /* udp streaming */
 #define DEFAULT_UDP_SOURCE                             "udpsrc"
@@ -120,20 +125,22 @@ typedef struct __media_streamer_ini {
 /* video format defaults */
 #define DEFAULT_VIDEO_ENCODER                          "omxh264enc"
 #define DEFAULT_VIDEO_DECODER                          "omxh264dec"
-#define DEFAULT_VIDEO_PARSER                           "h264parse"
-#define DEFAULT_VIDEO_RTPPAY                           "rtph264pay"
-#define DEFAULT_VIDEO_RTPDEPAY                         "rtph264depay"
+#define DEFAULT_VIDEO_PARSER                           "h263parse"
+#define DEFAULT_VIDEO_RTPPAY                           "rtph263pay"
+#define DEFAULT_VIDEO_RTPDEPAY                         "rtph263depay"
 
 /* audio format defaults */
-#define DEFAULT_AUDIO_ENCODER                          "omxh264enc"
-#define DEFAULT_AUDIO_DECODER                          "omxh264dec"
-#define DEFAULT_AUDIO_PARSER                           "h264parse"
-#define DEFAULT_AUDIO_RTPPAY                           "rtph264pay"
-#define DEFAULT_AUDIO_RTPDEPAY                         "rtph264depay"
+#define DEFAULT_AUDIO_RTPPAY                           "rtpL16pay"
+#define DEFAULT_AUDIO_RTPDEPAY                         "rtpL16depay"
 
 #define MEDIA_STREAMER_DEFAULT_CAMERA_FORMAT "video/x-raw,width=320,height=240"
 #define MEDIA_STREAMER_DEFAULT_AUDIO_FORMAT "audio/x-raw,channels=1,rate=44100,format=S16BE"
-#define MEDIA_STREAMER_DEFAULT_ENCODER_FORMAT "video/x-h264,stream-format=byte-stream,profile=high"
+#define MEDIA_STREAMER_DEFAULT_ENCODER_FORMAT "video/x-h263,stream-format=byte-stream,profile=high"
+
+#define MS_ELEMENT_IS_SINK(el) g_str_has_suffix(el, "sink")
+#define MS_ELEMENT_IS_SOURCE(el) g_str_has_suffix(el, "source")
+#define MS_ELEMENT_IS_AUDIO(el) g_str_has_prefix(el, "audio")
+#define MS_ELEMENT_IS_VIDEO(el) g_str_has_prefix(el, "video")
 
 #define MEDIA_STREAMER_DEFAULT_DOT_DIR "/tmp"
 #define MEDIA_STREAMER_DEFAULT_INI \
@@ -216,12 +223,19 @@ gchar *__ms_ini_get_string(dictionary *dict, const char *ini_path,
                            char *default_str);
 
 /**
- * @brief Converts Media Format mime type into string.
+ * @brief Converts Media Format mime type into Caps media format string.
  *
  * @since_tizen 3.0
  */
 const gchar *__ms_convert_mime_to_string(media_format_mimetype_e mime);
 
+/**
+ * @brief Converts Caps stream format into Media Format mime type.
+ *
+ * @since_tizen 3.0
+ */
+media_format_mimetype_e __ms_convert_string_format_to_mime(const char *format_type);
+
 #ifdef __cplusplus
 }
 #endif
index 459ff70..5e3099b 100755 (executable)
@@ -29,7 +29,7 @@
 * Public Implementation
 */
 
-int media_streamer_src_create(media_streamer_src_type_e type,
+int media_streamer_node_create_src(media_streamer_node_src_type_e type,
                               media_streamer_node_h *src)
 {
        int ret = MEDIA_STREAMER_ERROR_NONE;
@@ -41,7 +41,8 @@ int media_streamer_src_create(media_streamer_src_type_e type,
        ms_retvm_if(ms_src == NULL, MEDIA_STREAMER_ERROR_INVALID_OPERATION, "Error allocation memory");
 
        ms_src->type = MEDIA_STREAMER_NODE_TYPE_SRC;
-       ms_src->subtype = (media_streamer_src_type_e)type;
+       ms_src->subtype = (media_streamer_node_src_type_e)type;
+
        ret = __ms_src_node_create(ms_src);
        if (ret != MEDIA_STREAMER_ERROR_NONE) {
                MS_SAFE_FREE(ms_src);
@@ -55,7 +56,7 @@ int media_streamer_src_create(media_streamer_src_type_e type,
        return ret;
 }
 
-int media_streamer_sink_create(media_streamer_sink_type_e type,
+int media_streamer_node_create_sink(media_streamer_node_sink_type_e type,
                                media_streamer_node_h *sink)
 {
        int ret = MEDIA_STREAMER_ERROR_NONE;
@@ -67,7 +68,8 @@ int media_streamer_sink_create(media_streamer_sink_type_e type,
        ms_retvm_if(ms_sink == NULL, MEDIA_STREAMER_ERROR_INVALID_OPERATION, "Error allocation memory");
 
        ms_sink->type = MEDIA_STREAMER_NODE_TYPE_SINK;
-       ms_sink->subtype = (media_streamer_sink_type_e)type;
+       ms_sink->subtype = (media_streamer_node_sink_type_e)type;
+
        ret = __ms_sink_node_create(ms_sink);
        if (ret != MEDIA_STREAMER_ERROR_NONE) {
                MS_SAFE_FREE(ms_sink);
@@ -119,15 +121,42 @@ int media_streamer_node_destroy(media_streamer_node_h node)
                /* This node was not added into any media streamer */
                __ms_node_destroy(ms_node);
        } else {
-               int ret = __ms_node_remove_from_table(ms_node->parent_streamer->nodes_table, ms_node);
-               ms_retvm_if(ret != MEDIA_STREAMER_ERROR_NONE, MEDIA_STREAMER_ERROR_INVALID_OPERATION,
-                           "Current key was not removed from nodes_table");
+               ms_error("Node destroy error: needed to unlink node and remove it from media streamer before destroying.");
+               return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
        }
 
        ms_info("Node destroyed successfully");
        return MEDIA_STREAMER_ERROR_NONE;
 }
 
+int media_streamer_node_remove(media_streamer_h streamer,
+                               media_streamer_node_h node)
+{
+       media_streamer_node_s *ms_node = (media_streamer_node_s *)node;
+       media_streamer_s *ms_streamer = (media_streamer_s *)streamer;
+
+       ms_retvm_if(ms_streamer == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+       ms_retvm_if(ms_node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+       ms_retvm_if(ms_streamer->nodes_table == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+
+       ms_retvm_if(ms_streamer != ms_node->parent_streamer, MEDIA_STREAMER_ERROR_INVALID_PARAMETER,
+                   "Node [%s] added into another Media Streamer object", ms_node->name);
+
+       g_mutex_lock(&ms_streamer->mutex_lock);
+
+       if (g_hash_table_steal(ms_streamer->nodes_table, (gpointer)ms_node->name) &&
+           __ms_element_unlink(ms_node->gst_element)) {
+               ms_node->parent_streamer = NULL;
+               ms_info("Node removed from Media Streamer");
+       } else {
+               ms_error("Error: Node [%s] remove failed", ms_node->name);
+               return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+       }
+       g_mutex_unlock(&ms_streamer->mutex_lock);
+
+       return MEDIA_STREAMER_ERROR_NONE;
+}
+
 int media_streamer_node_add(media_streamer_h streamer,
                             media_streamer_node_h node)
 {
@@ -236,8 +265,6 @@ int media_streamer_create(media_streamer_h *streamer)
                ms_error("Error creating Media Streamer");
                __ms_streamer_destroy(ms_streamer);
 
-               g_mutex_clear(&ms_streamer->mutex_lock);
-
                return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
        }
 
@@ -260,9 +287,6 @@ int media_streamer_destroy(media_streamer_h streamer)
 
        __ms_streamer_destroy(ms_streamer);
 
-       g_mutex_unlock(&ms_streamer->mutex_lock);
-       g_mutex_clear(&ms_streamer->mutex_lock);
-
        ms_info("Media Streamer destroyed successfully");
 
        return MEDIA_STREAMER_ERROR_NONE;
@@ -272,11 +296,32 @@ int media_streamer_set_error_cb(media_streamer_h streamer,
                                 media_streamer_error_cb callback,
                                 void *data)
 {
+       media_streamer_s *ms_streamer = (media_streamer_s *)streamer;
+       ms_retvm_if(ms_streamer == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+       ms_retvm_if(callback == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Callback is NULL");
+
+       g_mutex_lock(&ms_streamer->mutex_lock);
+
+       ms_streamer->error_cb.callback = callback;
+       ms_streamer->error_cb.user_data = data;
+
+       g_mutex_unlock(&ms_streamer->mutex_lock);
+
        return MEDIA_STREAMER_ERROR_NONE;
 }
 
 int media_streamer_unset_error_cb(media_streamer_h streamer)
 {
+       media_streamer_s *ms_streamer = (media_streamer_s *)streamer;
+       ms_retvm_if(ms_streamer == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+
+       g_mutex_lock(&ms_streamer->mutex_lock);
+
+       ms_streamer->error_cb.callback = NULL;
+       ms_streamer->error_cb.user_data = NULL;
+
+       g_mutex_unlock(&ms_streamer->mutex_lock);
+
        return MEDIA_STREAMER_ERROR_NONE;
 }
 
@@ -284,11 +329,32 @@ int media_streamer_set_state_change_cb(media_streamer_h streamer,
                                        media_streamer_state_changed_cb callback,
                                        void *data)
 {
+       media_streamer_s *ms_streamer = (media_streamer_s *)streamer;
+       ms_retvm_if(ms_streamer == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+       ms_retvm_if(callback == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Callback is NULL");
+
+       g_mutex_lock(&ms_streamer->mutex_lock);
+
+       ms_streamer->state_changed_cb.callback = callback;
+       ms_streamer->state_changed_cb.user_data = data;
+
+       g_mutex_unlock(&ms_streamer->mutex_lock);
+
        return MEDIA_STREAMER_ERROR_NONE;
 }
 
 int media_streamer_unset_state_change_cb(media_streamer_h streamer)
 {
+       media_streamer_s *ms_streamer = (media_streamer_s *)streamer;
+       ms_retvm_if(ms_streamer == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+
+       g_mutex_lock(&ms_streamer->mutex_lock);
+
+       ms_streamer->state_changed_cb.callback = NULL;
+       ms_streamer->state_changed_cb.user_data = NULL;
+
+       g_mutex_unlock(&ms_streamer->mutex_lock);
+
        return MEDIA_STREAMER_ERROR_NONE;
 }
 
@@ -296,11 +362,33 @@ int media_streamer_src_set_buffer_status_cb(media_streamer_node_h source,
                                             media_streamer_custom_buffer_status_cb callback,
                                             void *user_data)
 {
+       media_streamer_node_s *ms_src = (media_streamer_node_s *)source;
+       media_streamer_callback_s *src_callback = NULL;
+       ms_retvm_if(ms_src == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+
+       if (!ms_src->callbacks_structure) {
+               src_callback = (media_streamer_callback_s *) calloc(1, sizeof(media_streamer_callback_s));
+               ms_retvm_if(src_callback == NULL, MEDIA_STREAMER_ERROR_INVALID_OPERATION, "Error allocation memory");
+       } else {
+               src_callback = (media_streamer_callback_s *)ms_src->callbacks_structure;
+       }
+
+       src_callback->callback = callback;
+       src_callback->user_data = user_data;
+
+       ms_src->callbacks_structure = (void *)src_callback;
        return MEDIA_STREAMER_ERROR_NONE;
 }
 
 int media_streamer_src_unset_buffer_status_cb(media_streamer_node_h source)
 {
+       media_streamer_node_s *ms_src = (media_streamer_node_s *)source;
+       ms_retvm_if(ms_src == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+
+       media_streamer_callback_s *src_callback = (media_streamer_callback_s *) ms_src->callbacks_structure;
+       src_callback->callback = NULL;
+       src_callback->user_data = NULL;
+
        return MEDIA_STREAMER_ERROR_NONE;
 }
 
@@ -308,11 +396,34 @@ int media_streamer_sink_set_data_ready_cb(media_streamer_node_h sink,
                                           media_streamer_sink_data_ready_cb callback,
                                           void *data)
 {
+       media_streamer_node_s *ms_sink = (media_streamer_node_s *)sink;
+       ms_retvm_if(ms_sink == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+
+       media_streamer_sink_callbacks_s *sink_callbacks = ms_sink->callbacks_structure;
+       if (!sink_callbacks) {
+               sink_callbacks = (media_streamer_sink_callbacks_s *) calloc(1, sizeof(media_streamer_sink_callbacks_s));
+               ms_retvm_if(sink_callbacks == NULL, MEDIA_STREAMER_ERROR_INVALID_OPERATION, "Error allocation memory");
+       }
+
+       sink_callbacks->data_ready_cb.callback = callback;
+       sink_callbacks->data_ready_cb.user_data = data;
+
+       ms_sink->callbacks_structure = (void *)sink_callbacks;
        return MEDIA_STREAMER_ERROR_NONE;
 }
 
-int media_streamer_sink_unset_data_ready_cb(media_streamer_node_h source)
+int media_streamer_sink_unset_data_ready_cb(media_streamer_node_h sink)
 {
+       media_streamer_node_s *ms_sink = (media_streamer_node_s *)sink;
+       ms_retvm_if(ms_sink == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+
+       media_streamer_sink_callbacks_s *sink_callbacks = ms_sink->callbacks_structure;
+       ms_retvm_if(sink_callbacks == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Callback didn't set yet");
+
+       sink_callbacks->data_ready_cb.callback = NULL;
+       sink_callbacks->data_ready_cb.user_data = NULL;
+
+       ms_sink->callbacks_structure = (void *)sink_callbacks;
        return MEDIA_STREAMER_ERROR_NONE;
 }
 
@@ -320,11 +431,34 @@ int media_streamer_sink_set_eos_cb(media_streamer_node_h sink,
                                    media_streamer_sink_eos_cb callback,
                                    void *data)
 {
+       media_streamer_node_s *ms_sink = (media_streamer_node_s *)sink;
+       ms_retvm_if(ms_sink == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+
+       media_streamer_sink_callbacks_s *sink_callbacks = ms_sink->callbacks_structure;
+       if (!sink_callbacks) {
+               sink_callbacks = (media_streamer_sink_callbacks_s *) calloc(1, sizeof(media_streamer_sink_callbacks_s));
+               ms_retvm_if(sink_callbacks == NULL, MEDIA_STREAMER_ERROR_INVALID_OPERATION, "Error allocation memory");
+       }
+
+       sink_callbacks->eos_cb.callback = callback;
+       sink_callbacks->eos_cb.user_data = data;
+
+       ms_sink->callbacks_structure = (void *)sink_callbacks;
        return MEDIA_STREAMER_ERROR_NONE;
 }
 
-int media_streamer_sink_unset_eos_cb(media_streamer_node_h source)
+int media_streamer_sink_unset_eos_cb(media_streamer_node_h sink)
 {
+       media_streamer_node_s *ms_sink = (media_streamer_node_s *)sink;
+       ms_retvm_if(ms_sink == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+
+       media_streamer_sink_callbacks_s *sink_callbacks = ms_sink->callbacks_structure;
+       ms_retvm_if(sink_callbacks == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Callback didn't set yet");
+
+       sink_callbacks->data_ready_cb.callback = NULL;
+       sink_callbacks->data_ready_cb.user_data = NULL;
+
+       ms_sink->callbacks_structure = (void *)sink_callbacks;
        return MEDIA_STREAMER_ERROR_NONE;
 }
 
@@ -379,52 +513,40 @@ int media_streamer_get_state(media_streamer_h streamer,
        return MEDIA_STREAMER_ERROR_NONE;
 }
 
-int media_streamer_seek(media_streamer_h streamer,
-                        media_streamer_time_value time)
-{
-       return MEDIA_STREAMER_ERROR_NONE;
-}
-
-int media_streamer_push_packet(media_streamer_node_h src,
+int media_streamer_node_push_packet(media_streamer_node_h src,
                                media_packet_h packet)
 {
-       return MEDIA_STREAMER_ERROR_NONE;
-}
-
-int media_streamer_pull_packet(media_streamer_node_h sink,
-                               media_packet_h *packet)
-{
-       return MEDIA_STREAMER_ERROR_NONE;
-}
-
-int media_streamer_node_set_format(media_streamer_node_h node,
-                                   media_format_h fmt)
-{
-       int ret = MEDIA_STREAMER_ERROR_NONE;
-       media_streamer_node_s *ms_node = (media_streamer_node_s *)node;
+       media_streamer_node_s *ms_node = (media_streamer_node_s *)src;
        ms_retvm_if(ms_node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Handle is NULL");
-       ms_retvm_if(fmt == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Format is NULL");
 
-       ret = __ms_element_set_fmt(node, fmt);
-       return ret;
+       ms_retvm_if(ms_node->type != MEDIA_STREAMER_NODE_TYPE_SRC,
+                       MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Node type must be Src type for pushing packets.");
+       ms_retvm_if(ms_node->subtype != MEDIA_STREAMER_NODE_SRC_TYPE_CUSTOM,
+                       MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Source Node must be a custom type for pushing packets.");
+
+       return __ms_element_push_packet(ms_node->gst_element, packet);
 }
 
-int media_streamer_node_get_format(media_streamer_node_h node,
-                                   media_format_h *fmt)
+int media_streamer_node_pull_packet(media_streamer_node_h sink,
+                               media_packet_h *packet)
 {
-       int ret = MEDIA_STREAMER_ERROR_NONE;
-       media_streamer_node_s *ms_node = (media_streamer_node_s *)node;
+       media_streamer_node_s *ms_node = (media_streamer_node_s *)sink;
        ms_retvm_if(ms_node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Handle is NULL");
-       ms_retvm_if(fmt == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Format is NULL");
+       ms_retvm_if(packet == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Media packet is NULL");
 
+       ms_retvm_if(ms_node->gst_element == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+       ms_retvm_if(ms_node->type != MEDIA_STREAMER_NODE_TYPE_SINK,
+                       MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Node type must be Sink type for pulling packets.");
+       ms_retvm_if(ms_node->subtype != MEDIA_STREAMER_NODE_SINK_TYPE_CUSTOM,
+                       MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Sink Node must be a custom type for pulling packets.");
 
-       return ret;
+       return __ms_element_pull_packet(ms_node->gst_element, packet);
 }
 
 int media_streamer_node_link(media_streamer_node_h src_node,
-                             const char *src_pad,
+                             const char *src_pad_name,
                              media_streamer_node_h dest_node,
-                             const char *sink_pad)
+                             const char *sink_pad_name)
 {
        int ret = MEDIA_STREAMER_ERROR_NONE;
        media_streamer_node_s *ms_src_node = (media_streamer_node_s *)src_node;
@@ -435,14 +557,14 @@ int media_streamer_node_link(media_streamer_node_h src_node,
        gchar *src_element_name = gst_element_get_name(ms_src_node->gst_element);
        gchar *sink_element_name = gst_element_get_name(ms_dest_node->gst_element);
 
-       ms_retvm_if(src_pad == NULL, MEDIA_STREAMER_ERROR_INVALID_OPERATION, "Pad is NULL");
-       ms_retvm_if(sink_pad == NULL, MEDIA_STREAMER_ERROR_INVALID_OPERATION, "Pad is NULL");
+       ms_retvm_if(src_pad_name == NULL, MEDIA_STREAMER_ERROR_INVALID_OPERATION, "Pad is NULL");
+       ms_retvm_if(sink_pad_name == NULL, MEDIA_STREAMER_ERROR_INVALID_OPERATION, "Pad is NULL");
 
        gboolean link_ret;
 
-       link_ret = gst_element_link_pads(ms_src_node->gst_element, src_pad, ms_dest_node->gst_element, sink_pad);
+       link_ret = gst_element_link_pads(ms_src_node->gst_element, src_pad_name, ms_dest_node->gst_element, sink_pad_name);
        if (!link_ret) {
-               ms_error("Can not link [%s]->%s pad to [%s]->%s pad, ret code [%d] ", src_pad, sink_pad, src_element_name, sink_element_name, link_ret);
+               ms_error("Can not link [%s]->%s pad to [%s]->%s pad, ret code [%d] ", src_pad_name, sink_pad_name, src_element_name, sink_element_name, link_ret);
                ret = MEDIA_STREAMER_ERROR_INVALID_OPERATION;
        }
 
@@ -451,10 +573,31 @@ int media_streamer_node_link(media_streamer_node_h src_node,
        return ret;
 }
 
+int media_streamer_node_set_pad_format(media_streamer_node_h node,
+                                       const char *pad_name,
+                                       media_format_h fmt)
+{
+       media_streamer_node_s *ms_node = (media_streamer_node_s *)node;
+       ms_retvm_if(ms_node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+       ms_retvm_if(fmt == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Format is NULL");
+
+       /* By default it sets format to object's property 'caps'*/
+       return __ms_element_set_fmt(node, fmt);
+}
+
 int media_streamer_node_get_pad_format(media_streamer_node_h node,
-                                       char **in_fmt,
-                                       char **out_fmt)
+                                       const char *pad_name,
+                                       media_format_h *fmt)
 {
+       media_streamer_node_s *ms_node = (media_streamer_node_s *)node;
+       ms_retvm_if(ms_node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+       ms_retvm_if(pad_name == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Empty pad name");
+       ms_retvm_if(fmt == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Format is NULL");
+
+       *fmt = __ms_element_get_pad_fmt(ms_node->gst_element, pad_name);
+
+       ms_retvm_if(*fmt == NULL, MEDIA_STREAMER_ERROR_INVALID_OPERATION, "Error while getting node fmt");
+
        return MEDIA_STREAMER_ERROR_NONE;
 }
 
@@ -475,8 +618,8 @@ int media_streamer_node_set_params(media_streamer_node_h node,
        return ret;
 }
 
-int media_streamer_node_get_param_list(media_streamer_node_h node,
-                                       bundle **param_list)
+int media_streamer_node_get_params(media_streamer_node_h node,
+                                   bundle **param_list)
 {
        media_streamer_node_s *ms_node = (media_streamer_node_s *)node;
        ms_retvm_if(ms_node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Handle is NULL");
@@ -497,3 +640,29 @@ int media_streamer_node_get_param_list(media_streamer_node_h node,
        *param_list = ms_params;
        return MEDIA_STREAMER_ERROR_NONE;
 }
+
+int media_streamer_node_set_param(media_streamer_node_h node,
+                                 const char *param_name, const char *param_value)
+{
+       media_streamer_node_s *ms_node = (media_streamer_node_s *)node;
+       ms_retvm_if(ms_node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+       ms_retvm_if(ms_node->gst_element == NULL && ms_node->set_param,
+                   MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+       ms_retvm_if(param_name == NULL || param_value == NULL,
+                   MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Parameters name or value is NULL");
+
+       return ms_node->set_param(ms_node, param_name, param_value);
+}
+
+int media_streamer_node_get_param(media_streamer_node_h node,
+                                  const char *param_name, char **param_value)
+{
+       media_streamer_node_s *ms_node = (media_streamer_node_s *)node;
+       ms_retvm_if(ms_node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+       ms_retvm_if(param_name == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Param name is NULL");
+
+  // TBD
+
+       return MEDIA_STREAMER_ERROR_NONE;
+}
+
index b63ce9a..290539e 100755 (executable)
 #include <bundle.h>
 #include <media_streamer_gst.h>
 
-#define MS_ELEMENT_IS_SINK(el) g_str_has_suffix(el, "sink")
-#define MS_ELEMENT_IS_SOURCE(el) g_str_has_suffix(el, "source")
-#define MS_ELEMENT_IS_AUDIO(el) g_str_has_prefix(el, "audio")
-#define MS_ELEMENT_IS_VIDEO(el) g_str_has_prefix(el, "video")
-
 void __ms_generate_dots(GstElement *bin, gchar *name_tag)
 {
        gchar *dot_name;
@@ -83,7 +78,7 @@ static int __ms_add_ghostpad(GstElement *gst_element,
        if (!gst_element || !pad_name) {
                ghost_pad = gst_ghost_pad_new_no_target(ghost_pad_name, GST_PAD_SRC);
                gst_element_add_pad(GST_ELEMENT(gst_bin), ghost_pad);
-               ms_info("Added %s empty ghostpad into [%s]", bin_name);
+               ms_info("Added [%s] empty ghostpad into [%s]", ghost_pad_name, bin_name);
                ret = MEDIA_STREAMER_ERROR_NONE;
        } else {
                gchar *element_name = gst_element_get_name(gst_element);
@@ -149,7 +144,7 @@ static GObject *__ms_get_property_owner(GstElement *element, const gchar *key, G
        return obj;
 }
 
-static void __ms_element_set_property(GstElement *element, const gchar *key, const gchar *param_value)
+gboolean __ms_element_set_property(GstElement *element, const gchar *key, const gchar *param_value)
 {
        gchar *element_name = gst_element_get_name(element);
        GValue value = G_VALUE_INIT;
@@ -158,7 +153,7 @@ static void __ms_element_set_property(GstElement *element, const gchar *key, con
        if (obj == NULL) {
                ms_debug("Element [%s] does not have property [%s].", element_name, key);
                MS_SAFE_GFREE(element_name);
-               return;
+               return FALSE;
        }
 
        switch (G_VALUE_TYPE(&value)) {
@@ -233,15 +228,16 @@ static void __ms_element_set_property(GstElement *element, const gchar *key, con
 
                                if (!caps) {
                                        ms_error("Can not create caps from param value.");
+                                       return FALSE;
                                } else {
                                        ms_info("Create Caps from params and set to the object.");
                                        g_object_set(obj, key, caps, NULL);
                                        gst_caps_unref(caps);
                                }
-                               return;
+                               return TRUE;
                        } else {
                                ms_info("Got unknown type with param->value_type [%d]", G_VALUE_TYPE(&value));
-                               return;
+                               return FALSE;
                        }
                        break;
        }
@@ -249,6 +245,57 @@ static void __ms_element_set_property(GstElement *element, const gchar *key, con
        MS_SAFE_GFREE(element_name);
 }
 
+gboolean __ms_element_unlink(GstElement *element)
+{
+       gboolean ret = TRUE;
+       GstPad *pad = NULL;
+       gchar *pad_name = NULL;
+
+       gchar *peer_pad_name = NULL;
+       GstPad *peer_pad = NULL;
+       GstElement *parent = NULL;
+
+       GValue elem = G_VALUE_INIT;
+       GstIterator *pad_iterator = gst_element_iterate_pads(element);
+
+       while (GST_ITERATOR_OK == gst_iterator_next(pad_iterator, &elem)) {
+               pad = (GstPad *)g_value_get_object(&elem);
+               pad_name = gst_pad_get_name(pad);
+
+               if (gst_pad_is_linked(pad)) {
+                       peer_pad = gst_pad_get_peer(pad);
+                       peer_pad_name = gst_pad_get_name(peer_pad);
+
+                       gboolean gst_ret = GST_PAD_IS_SRC(pad) ?
+                                          gst_pad_unlink(pad, peer_pad) :
+                                          gst_pad_unlink(peer_pad, pad);
+
+                       if (!gst_ret) {
+                               ms_error("Filed to unlink pad [%s] from peer pad \n", pad_name);
+                               ret = ret && FALSE;
+                       }
+
+                       MS_SAFE_GFREE(peer_pad_name);
+                       MS_SAFE_UNREF(peer_pad);
+               }
+
+               MS_SAFE_GFREE(pad_name);
+               g_value_reset(&elem);
+       }
+       g_value_unset(&elem);
+       gst_iterator_free(pad_iterator);
+
+       /*Remove node's element from bin and reference saving*/
+       parent = gst_element_get_parent(element);
+
+       if (parent != NULL) {
+               gst_object_ref(element);
+               ret = ret && gst_bin_remove(GST_BIN(parent), element);
+       }
+
+       return ret;
+}
+
 #if 0
 static void __ms_link_elements_on_pad_added_cb(GstPad *new_pad, GstElement *sink_element)
 {
@@ -299,66 +346,102 @@ static void __ms_link_elements_on_pad_added_cb(GstPad *new_pad, GstElement *sink
        MS_SAFE_GFREE(new_pad_name);
        MS_SAFE_GFREE(peer_pad_name);
 }
+#endif
 
-static void __ms_got_rtpstream_on_pad_added_cb(media_streamer_node_s *ms_node, GstPad *new_pad, const gchar *compared_type)
+static GstElement *__ms_bin_find_element_by_klass(GstElement *sink_bin, const gchar *klass_name)
 {
-       GstPad *src_pad;
-       GstCaps *src_pad_caps = NULL;
-       GstStructure *src_pad_struct = NULL;
-
-       gchar *sink_element_name = NULL;
-       GstElement *sink_element;
-
        GValue elem = G_VALUE_INIT;
-       const gchar *depay_klass_name = "Codec/Depayloader/Network/RTP";
-       GstIterator *bin_iterator;
+       GstIterator *bin_iterator = gst_bin_iterate_sorted(GST_BIN(sink_bin));
+       GstElement *found_element;
+       gboolean found = FALSE;
 
-       gchar *new_pad_name = gst_pad_get_name(new_pad);
-       gchar *source_pad_name = g_strdup_printf("%s_source", compared_type);
-
-       bin_iterator = gst_bin_iterate_elements(GST_BIN(ms_node->parent_streamer->topology_bin));
        while (GST_ITERATOR_OK == gst_iterator_next(bin_iterator, &elem)) {
 
-               sink_element = (GstElement *)g_value_get_object(&elem);
-               sink_element_name = gst_element_get_name(sink_element);
+               found_element = (GstElement *)g_value_get_object(&elem);
+               const gchar *found_klass = gst_element_factory_get_klass(gst_element_get_factory(found_element));
 
-               const gchar *klass_name = gst_element_factory_get_klass(gst_element_get_factory(sink_element));
+               if (g_strrstr(found_klass, klass_name)) {
+                       found = TRUE;
+                       break;
+               }
 
-               if (g_strrstr(klass_name, depay_klass_name)) {
-                       src_pad = gst_element_get_static_pad(sink_element, "src");
-                       ms_retm_if(src_pad == NULL, "Src pad is NULL");
+               g_value_reset(&elem);
+       }
 
-                       src_pad_caps = gst_pad_query_caps(src_pad, NULL);
-                       src_pad_struct = gst_caps_get_structure(src_pad_caps, 0);
-                       const gchar *src_pad_type = gst_structure_get_name(src_pad_struct);
+       g_value_unset(&elem);
+       gst_iterator_free(bin_iterator);
+       return found ? found_element : NULL;
+}
 
-                       if (g_strrstr(src_pad_type, compared_type)) {
-                               ms_debug("Element to connect [%s] has type [%s] \n", sink_element_name, src_pad_type);
-                               GstPad *video_source_pad = gst_element_get_static_pad(ms_node->gst_element, source_pad_name);
+static gboolean __ms_sink_bin_prepare(GstElement *sink_bin, GstPad *source_pad)
+{
+       gboolean ret = FALSE;
+       GstPad *src_pad = NULL; //pad of unlinked inner element
 
-                               gst_ghost_pad_set_target(GST_GHOST_PAD(video_source_pad), new_pad);
-                               gst_pad_set_active(video_source_pad, TRUE);
-                               __ms_generate_dots(ms_node->parent_streamer->pipeline);
-                       }
+       GValue elem = G_VALUE_INIT;
+       GstIterator *bin_iterator;
 
-                       gst_caps_unref(src_pad_caps);
+       gchar *source_pad_name = gst_pad_get_name(source_pad);
 
-                       MS_SAFE_UNREF(src_pad);
+       GstElement *found_element = __ms_bin_find_element_by_klass(sink_bin, "Depayloader/Network/RTP");
+       if (!found_element) {
+               if (MS_ELEMENT_IS_AUDIO(source_pad_name)) {
+                       found_element = __ms_element_create(DEFAULT_AUDIO_RTPDEPAY, NULL);
+               } else {
+                       found_element = __ms_element_create("rtph263depay", NULL);
                }
-               g_value_reset(&elem);
+               gst_bin_add(GST_BIN(sink_bin), found_element);
        }
-       g_value_unset(&elem);
-       gst_iterator_free(bin_iterator);
-       MS_SAFE_GFREE(sink_element_name);
-       MS_SAFE_GFREE(source_pad_name);
-       MS_SAFE_FREE(new_pad_name);
+       __ms_add_ghostpad(found_element, "sink", sink_bin, "sink");
+       src_pad = gst_element_get_static_pad(found_element, "src");
+
+       if (MS_ELEMENT_IS_AUDIO(source_pad_name)) {
+               found_element = __ms_bin_find_element_by_klass(sink_bin, "Converter/Audio");
+               if (!found_element) {
+                       found_element = __ms_element_create(DEFAULT_AUDIO_CONVERT, NULL);
+                       gst_bin_add(GST_BIN(sink_bin), found_element);
+               }
+//                     GstElement *resample = __ms_element_create(DEFAULT_AUDIO_RESAMPLE, NULL);
+//                     gst_bin_add(GST_BIN(sink_bin), resample);
+//                     g_assert(gst_element_link(found_element, resample));
+       } else if (MS_ELEMENT_IS_VIDEO(source_pad_name)) {
+               found_element = __ms_bin_find_element_by_klass(sink_bin, "Generic/Bin");
+               if (!found_element) {
+                       dictionary *dict = NULL;
+                       __ms_load_ini_dictionary(&dict);
+                       found_element = __ms_video_decoder_element_create(dict, MEDIA_FORMAT_H263);
+                       gst_bin_add(GST_BIN(sink_bin), found_element);
+                       __ms_destroy_ini_dictionary(dict);
+               }
+       } else {
+               return FALSE;
+       }
+
+       if (!gst_pad_is_linked(src_pad))
+       {
+               GstPad *sink_pad = gst_element_get_static_pad(found_element, "sink");
+               g_assert(!gst_pad_link(src_pad, sink_pad));
+               MS_SAFE_UNREF(sink_pad);
+       }
+       MS_SAFE_UNREF(src_pad);
+
+       src_pad = gst_element_get_static_pad(found_element, "src");
+       found_element = __ms_bin_find_element_by_klass(sink_bin, "Sink/");
+       if (!gst_pad_is_linked(src_pad))
+       {
+               GstPad *sink_pad = gst_element_get_static_pad(found_element, "sink");
+               g_assert(!gst_pad_link(src_pad, sink_pad));
+               MS_SAFE_UNREF(sink_pad);
+       }
+       MS_SAFE_UNREF(src_pad);
+       ret = TRUE;
+
+       return ret;
 }
-#endif
 
 static void __ms_rtpbin_pad_added_cb(GstElement *src, GstPad *new_pad, gpointer user_data)
 {
        GstCaps *src_pad_caps = NULL;
-       GstStructure *src_pad_struct = NULL;
        GstPad *target_pad = NULL;
 
        gchar *new_pad_name = NULL;
@@ -373,49 +456,55 @@ static void __ms_rtpbin_pad_added_cb(GstElement *src, GstPad *new_pad, gpointer
 
        target_pad = gst_ghost_pad_get_target(GST_GHOST_PAD(new_pad));
        src_pad_caps = gst_pad_query_caps(target_pad, NULL);
-       src_pad_struct = gst_caps_get_structure(src_pad_caps, 0);
 
-       const gchar *src_pad_type = gst_structure_get_string(src_pad_struct, "media");
-       ms_debug("type is [%s]", src_pad_type);
-
-       if (ms_node->parent_streamer == NULL) {
-               ms_error("Node doesn`t have parent streamer:\n");
-       } else {
+       if (ms_node->parent_streamer && !gst_caps_is_any(src_pad_caps)) {
                gchar *source_pad_name = NULL;
                GstElement *sink_bin = NULL;
-               if (g_strrstr(src_pad_type, "video")) {
+               GstStructure *src_pad_struct = NULL;
+               src_pad_struct = gst_caps_get_structure(src_pad_caps, 0);
+
+               const gchar *src_pad_type = gst_structure_get_string(src_pad_struct, "media");
+               ms_debug("type is [%s]", src_pad_type);
+               if (MS_ELEMENT_IS_VIDEO(src_pad_type)) {
                        source_pad_name = g_strdup_printf("%s_source", "video");
                        sink_bin = ms_node->parent_streamer->sink_video_bin;
-               } else if (g_strrstr(src_pad_type, "audio")) {
+               } else if (MS_ELEMENT_IS_AUDIO(src_pad_type)) {
                        source_pad_name = g_strdup_printf("%s_source", "audio");
                        sink_bin = ms_node->parent_streamer->sink_audio_bin;
                }
 
                if (source_pad_name != NULL) {
-                       if (gst_object_get_parent(GST_OBJECT(sink_bin)) == NULL) {
-                               gst_bin_add(GST_BIN(ms_node->parent_streamer->pipeline), sink_bin);
-                       }
-                       gst_element_sync_state_with_parent(sink_bin);
-
 
                        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);
                        gst_pad_set_active(source_pad, TRUE);
 
-                       GstPad *sink_pad = gst_bin_find_unlinked_pad(GST_BIN(sink_bin), GST_PAD_SINK);
-                       if (sink_pad != NULL) {
-                               __ms_add_ghostpad(gst_pad_get_parent(sink_pad), "sink", sink_bin, "sink");
+                       g_mutex_lock(&ms_node->parent_streamer->mutex_lock);
+                       if (__ms_sink_bin_prepare(sink_bin, source_pad)) {
+
+                               if (gst_object_get_parent(GST_OBJECT(sink_bin)) == NULL) {
+                                       gst_bin_add(GST_BIN(ms_node->parent_streamer->pipeline), sink_bin);
+                               }
+
+                               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);
                                }
-                               MS_SAFE_UNREF(sink_pad);
+                       } else {
+                               ms_error("Failed to prepare sink_bin for pad type [%s]\n", src_pad_type);
                        }
+
+                       g_mutex_unlock(&ms_node->parent_streamer->mutex_lock);
+
                        MS_SAFE_UNREF(source_pad);
                        MS_SAFE_GFREE(source_pad_name);
                }
+       } else {
+               ms_debug("Node doesn`t have parent streamer or caps media type\n");
        }
 
        gst_caps_unref(src_pad_caps);
@@ -444,9 +533,12 @@ int __ms_element_set_state(GstElement *gst_element, GstState gst_state)
 
 GstElement *__ms_element_create(const char *plugin_name, const char *name)
 {
+       GstElement *plugin_elem = NULL;
        ms_retvm_if(plugin_name == NULL, (GstElement *)NULL, "Error empty plugin name");
        ms_info("Creating [%s] element", plugin_name);
-       return gst_element_factory_make(plugin_name, name);
+       plugin_elem = gst_element_factory_make(plugin_name, name);
+       ms_retvm_if(plugin_elem == NULL, (GstElement *)NULL, "Error creating element [%s]", plugin_name);
+       return plugin_elem;
 }
 
 GstElement *__ms_camera_element_create(const char *camera_plugin_name)
@@ -484,7 +576,7 @@ GstElement *__ms_video_encoder_element_create(dictionary *dict , media_format_mi
        char *format_prefix = NULL;
 
        format_prefix = g_strdup_printf("%s:encoder", __ms_convert_mime_to_string(mime));
-       plugin_name = __ms_ini_get_string(dict, format_prefix, DEFAULT_VIDEO_DECODER);
+       plugin_name = __ms_ini_get_string(dict, format_prefix, DEFAULT_VIDEO_ENCODER);
        GstElement *encoder_elem = __ms_element_create(plugin_name, NULL);
        MS_SAFE_FREE(format_prefix);
        MS_SAFE_FREE(plugin_name);
@@ -501,7 +593,7 @@ GstElement *__ms_video_encoder_element_create(dictionary *dict , media_format_mi
        ms_retvm_if(!filter || !encoder_elem || !encoder_bin || !encoder_parser, (GstElement *)NULL,
                    "Error: creating elements for video encoder bin");
 
-       format_prefix = g_strdup_printf("video/x-%s,stream-format=byte-stream,profile=high",
+       format_prefix = g_strdup_printf("video/x-%s,stream-format=byte-stream,profile=main",
                                        __ms_convert_mime_to_string(mime));
        GstCaps *videoCaps = gst_caps_from_string(format_prefix);
        g_object_set(G_OBJECT(filter), "caps", videoCaps, NULL);
@@ -624,8 +716,8 @@ GstElement *__ms_rtp_element_create(media_streamer_node_s *ms_node)
        return rtp_container;
 }
 
-static gboolean __ms_get_rtp_elements(media_streamer_node_s *ms_node,
-                                      GstElement **rtp_elem, GstElement **rtcp_elem, const gchar *elem_name)
+gboolean __ms_get_rtp_elements(media_streamer_node_s *ms_node,
+                               GstElement **rtp_elem, GstElement **rtcp_elem, const gchar *elem_name)
 {
        gboolean ret = FALSE;
        gchar *rtp_elem_name = NULL;
@@ -705,52 +797,6 @@ static gboolean __ms_get_rtp_elements(media_streamer_node_s *ms_node,
        return ret;
 }
 
-int __ms_rtp_set_param(
-    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_NONE, "Error: empty node");
-
-       gchar **tokens = NULL;
-       gchar *elem_name = NULL;
-       guint i = 0;
-       GstElement *rtp_elem = NULL;
-       GstElement *rtcp_elem = NULL;
-
-       tokens = g_strsplit(param_key, ",", 3);
-       ms_retvm_if(tokens == NULL, MEDIA_STREAMER_ERROR_INVALID_OPERATION, "Invalid rtp parameter line.");
-       elem_name = tokens[0];
-
-       if (FALSE == __ms_get_rtp_elements(ms_node, &rtp_elem, &rtcp_elem, elem_name)) {
-               ms_error("Error: invalid parameter [%s]", param_key);
-               return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
-       }
-
-       for (i = 1; (tokens && tokens[i]); i++) {
-               ms_retvm_if(!rtp_elem || !rtcp_elem,
-                           MEDIA_STREAMER_ERROR_INVALID_OPERATION,
-                           "Error: [%s] did not found or created into streamer", tokens[i]);
-
-               if (!g_strcmp0(tokens[i], "port")) {
-                       __ms_element_set_property(rtp_elem, tokens[i], param_value);
-                       gchar *next_port = g_strdup(param_value);
-                       next_port[strlen(next_port) - 1] += 1;
-                       __ms_element_set_property(rtcp_elem, tokens[i], next_port);
-                       MS_SAFE_GFREE(next_port);
-               } else if (!g_strcmp0(tokens[i], "host") && MS_ELEMENT_IS_SINK(elem_name)) {
-                       __ms_element_set_property(rtp_elem, tokens[i], param_value);
-                       __ms_element_set_property(rtcp_elem, tokens[i], param_value);
-               } else if (!g_strcmp0(tokens[i], "format") && MS_ELEMENT_IS_SOURCE(elem_name)) {
-                       __ms_element_set_property(rtp_elem, "caps", param_value);
-               }
-
-       }
-       g_strfreev(tokens);
-
-       return MEDIA_STREAMER_ERROR_NONE;
-}
-
 int __ms_add_node_into_bin(media_streamer_s *ms_streamer, media_streamer_node_s *ms_node)
 {
        int ret = MEDIA_STREAMER_ERROR_NONE;
@@ -770,17 +816,17 @@ int __ms_add_node_into_bin(media_streamer_s *ms_streamer, media_streamer_node_s
                        break;
                case MEDIA_STREAMER_NODE_TYPE_SINK:
                        switch (ms_node->subtype) {
-                               case MEDIA_STREAMER_SINK_TYPE_SCREEN:
+                               case MEDIA_STREAMER_NODE_SINK_TYPE_SCREEN:
                                        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_SINK_TYPE_AUDIO:
+                               case MEDIA_STREAMER_NODE_SINK_TYPE_AUDIO:
                                        gst_ret = gst_bin_add(GST_BIN(ms_streamer->sink_audio_bin), ms_node->gst_element);
                                        bin_name = g_strdup(MEDIA_STREAMER_AUDIO_SINK_BIN_NAME);
                                        break;
                                default:
-                                       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);
+                                       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;
                        }
                        break;
@@ -1007,6 +1053,82 @@ static GstCaps *__ms_create_caps_from_fmt(media_format_h fmt)
        return caps;
 }
 
+static media_format_h __ms_create_fmt_from_caps(GstCaps *caps)
+{
+       media_format_h fmt;
+       GstStructure *pad_struct;
+       ms_retvm_if(caps == NULL, NULL, "Error: empty caps!");
+
+       if (gst_caps_is_any(caps)) {
+               ms_debug("Can not get format info from any caps!");
+               return NULL;
+       }
+
+       int fmt_ret = MEDIA_FORMAT_ERROR_NONE;
+
+       fmt_ret  = media_format_create(&fmt);
+       ms_retvm_if(fmt_ret != MEDIA_FORMAT_ERROR_NONE, NULL,
+                       "Error: while creating media format object, err[%d]!", fmt_ret);
+
+       pad_struct = gst_caps_get_structure(caps, 0);
+       const gchar *pad_type = gst_structure_get_name(pad_struct);
+       const gchar *pad_format = pad_type;
+
+       /* Got raw format type if needed */
+       if (g_strrstr(pad_type, "/x-raw")) {
+               pad_format = gst_structure_get_string(pad_struct, "format");
+       }
+
+       ms_debug("Pad type is [%s], format: [%s]", pad_type, pad_format);
+       if (MS_ELEMENT_IS_VIDEO(pad_type)) {
+               int width, height;
+               media_format_set_video_mime(fmt, __ms_convert_string_format_to_mime(pad_format));
+               gst_structure_get_int(pad_struct, "width", &width);
+               media_format_set_video_width(fmt, width);
+
+               gst_structure_get_int(pad_struct, "height", &height);
+               media_format_set_video_height(fmt, height);
+       } else if (MS_ELEMENT_IS_AUDIO(pad_type)) {
+               int channels, bps;
+               media_format_set_audio_mime(fmt, __ms_convert_string_format_to_mime(pad_format));
+               gst_structure_get_int(pad_struct, "channels", &channels);
+               media_format_set_audio_channel(fmt, channels);
+               gst_structure_get_int(pad_struct, "rate", &bps);
+               media_format_set_audio_avg_bps(fmt, bps);
+       }
+
+       return fmt;
+}
+
+media_format_h __ms_element_get_pad_fmt(GstElement *gst_element, const char *pad_name)
+{
+       media_format_h fmt;
+       GstCaps *caps = NULL;
+
+       GstPad *pad = gst_element_get_static_pad(gst_element, pad_name);
+       gchar *element_name = gst_element_get_name(gst_element);
+
+       if (pad == NULL) {
+               ms_error("Fail to get pad [%s] from element [%s].", pad_name, element_name);
+               MS_SAFE_FREE(element_name);
+               return NULL;
+       }
+
+       caps = gst_pad_get_allowed_caps(pad);
+       if (caps == NULL) {
+               ms_error("Fail to get caps from element [%s] and pad [%s].", element_name, pad_name);
+               MS_SAFE_FREE(element_name);
+               MS_SAFE_UNREF(pad);
+               return NULL;
+       }
+
+       fmt = __ms_create_fmt_from_caps(caps);
+
+       MS_SAFE_FREE(element_name);
+       MS_SAFE_UNREF(pad);
+       return fmt;
+}
+
 int __ms_element_set_fmt(media_streamer_node_s *node, media_format_h fmt)
 {
        GstCaps *caps = NULL;
@@ -1022,3 +1144,72 @@ int __ms_element_set_fmt(media_streamer_node_s *node, media_format_h fmt)
 
        return MEDIA_STREAMER_ERROR_NONE;
 }
+
+int __ms_element_push_packet(GstElement *src_element, media_packet_h packet)
+{
+       GstBuffer *buffer;
+       GstFlowReturn gst_ret = GST_FLOW_OK;
+       guint64 pts = 0;
+       guint64 duration = 0;
+       guchar *buffer_data = NULL;
+       guint64 size  = 0;
+
+       ms_retvm_if(src_element == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+
+       if (packet == NULL) {
+               g_signal_emit_by_name(G_OBJECT(src_element), "end-of-stream", &gst_ret, NULL);
+               return MEDIA_STREAMER_ERROR_NONE;
+       }
+
+       media_packet_get_buffer_size(packet, &size);
+       media_packet_get_buffer_data_ptr(packet, &buffer_data);
+       media_packet_get_pts(packet, &pts);
+       media_packet_get_duration(packet, &duration);
+
+       buffer = gst_buffer_new_wrapped(buffer_data, size);
+
+       GST_BUFFER_PTS(buffer) = pts;
+       GST_BUFFER_DURATION(buffer) = duration;
+
+       g_signal_emit_by_name(G_OBJECT(src_element), "push-buffer", buffer, &gst_ret, NULL);
+
+       gst_buffer_unref(buffer);
+
+       if (gst_ret != GST_FLOW_OK) {
+               return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+       }
+
+       return MEDIA_STREAMER_ERROR_NONE;
+}
+
+int __ms_element_pull_packet(GstElement *sink_element, media_packet_h *packet)
+{
+       GstBuffer *buffer = NULL;
+       GstFlowReturn gst_ret = GST_FLOW_OK;
+       GstSample *sample = NULL;
+       GstMapInfo map;
+
+       ms_retvm_if(sink_element == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+
+       /* Retrieve the buffer */
+       g_signal_emit_by_name(sink_element, "pull-sample", &sample, NULL);
+       ms_retvm_if(sample == NULL, MEDIA_STREAMER_ERROR_INVALID_OPERATION, "Pull sample failed!");
+
+       buffer = gst_sample_get_buffer(sample);
+       gst_buffer_map(buffer, &map, GST_MAP_READ);
+
+       media_format_h fmt = __ms_element_get_pad_fmt(sink_element, "sink");
+       ms_retvm_if(fmt == NULL, MEDIA_STREAMER_ERROR_INVALID_OPERATION,
+                       "Error while getting media format from sink pad");
+
+       media_packet_create_from_external_memory(&fmt, (void *)map.data, map.size, NULL, NULL, packet);
+       media_packet_set_pts(*packet, GST_BUFFER_PTS(buffer));
+       media_packet_set_dts(*packet, GST_BUFFER_DTS(buffer));
+       media_packet_set_pts(*packet, GST_BUFFER_DURATION(buffer));
+
+       media_format_unref(fmt);
+       gst_buffer_unmap(buffer, &map);
+       gst_sample_unref(sample);
+
+       return MEDIA_STREAMER_ERROR_NONE;
+}
index 7077070..0c22ee4 100755 (executable)
 #include <media_streamer_util.h>
 #include <media_streamer_gst.h>
 
+static 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");
+
+       __ms_element_set_property(ms_node->gst_element, param_key, param_value);
+
+       return MEDIA_STREAMER_ERROR_NONE;
+}
+
+static int __ms_rtp_node_set_property(media_streamer_node_s *ms_node,
+                                      const char *param_key,
+                                      const char *param_value)
+{
+       ms_retvm_if(!ms_node && !ms_node->gst_element, MEDIA_STREAMER_ERROR_INVALID_OPERATION, "Error: empty node");
+
+       gchar **tokens = NULL;
+       gchar *elem_name = NULL;
+       guint i = 0;
+       GstElement *rtp_elem = NULL;
+       GstElement *rtcp_elem = NULL;
+
+       tokens = g_strsplit(param_key, ",", 3);
+       ms_retvm_if(tokens == NULL, MEDIA_STREAMER_ERROR_INVALID_OPERATION, "Invalid rtp parameter line.");
+       elem_name = tokens[0];
+
+       if (FALSE == __ms_get_rtp_elements(ms_node, &rtp_elem, &rtcp_elem, elem_name)) {
+               ms_error("Error: invalid parameter [%s]", param_key);
+               g_strfreev(tokens);
+               return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+       }
+
+       for (i = 1; (tokens && tokens[i]); i++) {
+               ms_retvm_if(!rtp_elem || !rtcp_elem,
+                           MEDIA_STREAMER_ERROR_INVALID_OPERATION,
+                           "Error: [%s] did not found or created into streamer", tokens[i]);
+
+               if (!g_strcmp0(tokens[i], "port")) {
+                       __ms_element_set_property(rtp_elem, tokens[i], param_value);
+                       gchar *next_port = g_strdup(param_value);
+                       next_port[strlen(next_port) - 1] += 1;
+                       __ms_element_set_property(rtcp_elem, tokens[i], next_port);
+                       MS_SAFE_GFREE(next_port);
+               } else if (!g_strcmp0(tokens[i], "host") && MS_ELEMENT_IS_SINK(elem_name)) {
+                       __ms_element_set_property(rtp_elem, tokens[i], param_value);
+                       __ms_element_set_property(rtcp_elem, tokens[i], param_value);
+               } else if (!g_strcmp0(tokens[i], "format") && MS_ELEMENT_IS_SOURCE(elem_name)) {
+                       __ms_element_set_property(rtp_elem, "caps", param_value);
+               }
+
+       }
+       g_strfreev(tokens);
+
+       return MEDIA_STREAMER_ERROR_NONE;
+}
+
 int __ms_node_create(media_streamer_node_s *node,
                      media_format_h in_fmt,
                      media_format_h out_fmt)
@@ -35,6 +93,8 @@ int __ms_node_create(media_streamer_node_s *node,
 
        __ms_load_ini_dictionary(&dict);
 
+       node->set_param = (ms_node_set_param)__ms_node_set_property;
+
        switch (node->type) {
                case MEDIA_STREAMER_NODE_TYPE_VIDEO_ENCODER:
                        format_prefix = g_strdup_printf("%s:encoder", __ms_convert_mime_to_string(mime));
@@ -81,7 +141,7 @@ int __ms_node_create(media_streamer_node_s *node,
                        break;
                case MEDIA_STREAMER_NODE_TYPE_RTP:
                        node->gst_element = __ms_rtp_element_create(node);
-                       node->set_param = (media_streamer_node_set_param)__ms_rtp_set_param;
+                       node->set_param = (ms_node_set_param)__ms_rtp_node_set_property;
                        break;
                case MEDIA_STREAMER_NODE_TYPE_QUEUE:
                        node->gst_element = __ms_element_create(DEFAULT_QUEUE, NULL);
@@ -114,6 +174,35 @@ int __ms_node_create(media_streamer_node_s *node,
        return MEDIA_STREAMER_ERROR_NONE;
 }
 
+/* This signal callback is called when appsrc needs data, we add an idle handler
+ * to the mainloop to start pushing data into the appsrc */
+static void __ms_src_start_feed_cb(GstElement *pipeline, guint size, gpointer data)
+{
+       media_streamer_node_s *ms_src = (media_streamer_node_s *)data;
+       ms_retm_if(ms_src == NULL, "Handle is NULL");
+
+       if (ms_src->callbacks_structure != NULL) {
+               media_streamer_callback_s *src_callback = (media_streamer_callback_s *)ms_src->callbacks_structure;
+               media_streamer_custom_buffer_status_cb buffer_status_cb =
+                               (media_streamer_custom_buffer_status_cb) src_callback->callback;
+               buffer_status_cb((media_streamer_node_h)ms_src, MEDIA_STREAMER_CUSTOM_BUFFER_UNDERRUN, src_callback->user_data);
+       }
+}
+
+/* This callback is called when appsrc has enough data and we can stop sending.
+ * We remove the idle handler from the mainloop */
+static void __ms_src_stop_feed_cb(GstElement *pipeline, gpointer data)
+{
+       media_streamer_node_s *ms_src = (media_streamer_node_s *)data;
+       ms_retm_if(ms_src == NULL, "Handle is NULL");
+
+       if (ms_src->callbacks_structure != NULL) {
+               media_streamer_callback_s *src_callback = (media_streamer_callback_s *)ms_src->callbacks_structure;
+               media_streamer_custom_buffer_status_cb buffer_status_cb =
+                               (media_streamer_custom_buffer_status_cb) src_callback->callback;
+               buffer_status_cb((media_streamer_node_h)ms_src, MEDIA_STREAMER_CUSTOM_BUFFER_OVERFLOW, src_callback->user_data);
+       }
+}
 
 int __ms_src_node_create(media_streamer_node_s *node)
 {
@@ -124,41 +213,44 @@ int __ms_src_node_create(media_streamer_node_s *node)
 
        __ms_load_ini_dictionary(&dict);
 
+       node->set_param = (ms_node_set_param)__ms_node_set_property;
+
        switch (node->subtype) {
-               case MEDIA_STREAMER_SRC_TYPE_FILE:
+               case MEDIA_STREAMER_NODE_SRC_TYPE_FILE:
                        ms_error("Error: not implemented yet");
                        break;
-               case MEDIA_STREAMER_SRC_TYPE_RTSP:
+               case MEDIA_STREAMER_NODE_SRC_TYPE_RTSP:
                        node->gst_element = __ms_element_create(DEFAULT_UDP_SOURCE, NULL);
                        break;
-               case MEDIA_STREAMER_SRC_TYPE_HTTP:
+               case MEDIA_STREAMER_NODE_SRC_TYPE_HTTP:
                        ms_error("Error: not implemented yet");
                        break;
-               case MEDIA_STREAMER_SRC_TYPE_CAMERA:
+               case MEDIA_STREAMER_NODE_SRC_TYPE_CAMERA:
                        plugin_name = __ms_ini_get_string(dict,
                                                          "sources:camera_source", DEFAULT_CAMERA_SOURCE);
                        node->gst_element = __ms_camera_element_create(plugin_name);
 
                        break;
-               case MEDIA_STREAMER_SRC_TYPE_AUDIO_CAPTURE:
+               case MEDIA_STREAMER_NODE_SRC_TYPE_AUDIO_CAPTURE:
                        plugin_name = __ms_ini_get_string(dict,
                                                          "sources:audio_source", DEFAULT_AUDIO_SOURCE);
                        node->gst_element = __ms_element_create(plugin_name, NULL);
                        break;
-               case MEDIA_STREAMER_SRC_TYPE_VIDEO_CAPTURE:
+               case MEDIA_STREAMER_NODE_SRC_TYPE_VIDEO_CAPTURE:
                        plugin_name = __ms_ini_get_string(dict,
                                                          "sources:video_source", DEFAULT_VIDEO_SOURCE);
                        node->gst_element = __ms_element_create(plugin_name, NULL);
                        break;
-               case MEDIA_STREAMER_SRC_TYPE_VIDEO_TEST:
+               case MEDIA_STREAMER_NODE_SRC_TYPE_VIDEO_TEST:
                        node->gst_element = __ms_element_create(DEFAULT_VIDEO_TEST_SOURCE, NULL);
-                       g_object_set(G_OBJECT(node->gst_element), "is-live", true, NULL);
                        break;
-               case MEDIA_STREAMER_SRC_TYPE_AUDIO_TEST:
+               case MEDIA_STREAMER_NODE_SRC_TYPE_AUDIO_TEST:
                        node->gst_element = __ms_element_create(DEFAULT_AUDIO_TEST_SOURCE, NULL);
                        break;
-               case MEDIA_STREAMER_SRC_TYPE_CUSTOM:
-                       ms_error("Error: not implemented yet");
+               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);
                        break;
                default:
                        ms_error("Error: invalid Src node Type [%d]", node->subtype);
@@ -174,6 +266,38 @@ int __ms_src_node_create(media_streamer_node_s *node)
        return MEDIA_STREAMER_ERROR_NONE;
 }
 
+/* The appsink has received a buffer */
+static void __ms_sink_new_buffer_cb(GstElement *sink, gpointer *data)
+{
+       media_streamer_node_s *ms_sink = (media_streamer_node_s *)data;
+       ms_retm_if(ms_sink == NULL, "Handle is NULL");
+
+       if (ms_sink->callbacks_structure != NULL) {
+               media_streamer_sink_callbacks_s *sink_callbacks =
+                               (media_streamer_sink_callbacks_s *)ms_sink->callbacks_structure;
+               media_streamer_sink_data_ready_cb data_ready_cb =
+                               (media_streamer_sink_data_ready_cb) sink_callbacks->data_ready_cb.callback;
+
+               data_ready_cb((media_streamer_node_h)ms_sink, sink_callbacks->data_ready_cb.user_data);
+       }
+}
+
+/* The appsink has got eos */
+static void sink_eos(GstElement *sink, gpointer *data)
+{
+       media_streamer_node_s *ms_sink = (media_streamer_node_s *)data;
+       ms_retm_if(ms_sink == NULL, "Handle is NULL");
+
+       if (ms_sink->callbacks_structure != NULL) {
+               media_streamer_sink_callbacks_s *sink_callbacks =
+                               (media_streamer_sink_callbacks_s *)ms_sink->callbacks_structure;
+               media_streamer_sink_eos_cb eos_cb =
+                               (media_streamer_sink_eos_cb) sink_callbacks->eos_cb.callback;
+
+               eos_cb((media_streamer_node_h)ms_sink, sink_callbacks->eos_cb.user_data);
+       }
+}
+
 int __ms_sink_node_create(media_streamer_node_s *node)
 {
        ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Handle is NULL");
@@ -183,31 +307,36 @@ int __ms_sink_node_create(media_streamer_node_s *node)
 
        __ms_load_ini_dictionary(&dict);
 
+       node->set_param = (ms_node_set_param)__ms_node_set_property;
+
        switch (node->subtype) {
-               case MEDIA_STREAMER_SINK_TYPE_FILE:
+               case MEDIA_STREAMER_NODE_SINK_TYPE_FILE:
                        ms_error("Error: not implemented yet");
                        break;
-               case MEDIA_STREAMER_SINK_TYPE_RTSP:
+               case MEDIA_STREAMER_NODE_SINK_TYPE_RTSP:
                        node->gst_element = __ms_element_create(DEFAULT_UDP_SINK, NULL);
                        break;
-               case MEDIA_STREAMER_SINK_TYPE_HTTP:
+               case MEDIA_STREAMER_NODE_SINK_TYPE_HTTP:
                        ms_error("Error: not implemented yet");
                        break;
-               case MEDIA_STREAMER_SINK_TYPE_AUDIO:
+               case MEDIA_STREAMER_NODE_SINK_TYPE_AUDIO:
                        plugin_name = __ms_ini_get_string(dict,
                                                          "sinks:audio_sink", DEFAULT_AUDIO_SINK);
                        node->gst_element = __ms_element_create(plugin_name, NULL);
                        break;
-               case MEDIA_STREAMER_SINK_TYPE_SCREEN:
+               case MEDIA_STREAMER_NODE_SINK_TYPE_SCREEN:
                        plugin_name = __ms_ini_get_string(dict,
                                                          "sinks:video_sink", DEFAULT_VIDEO_SINK);
                        node->gst_element = __ms_element_create(plugin_name, NULL);
                        break;
-               case MEDIA_STREAMER_SINK_TYPE_FAKE:
+               case MEDIA_STREAMER_NODE_SINK_TYPE_FAKE:
                        node->gst_element = __ms_element_create(DEFAULT_FAKE_SINK, NULL);
                        break;
-               case MEDIA_STREAMER_SINK_TYPE_CUSTOM:
-
+               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);
                        break;
                default:
                        ms_error("Error: invalid Sink node Type [%d]", node->subtype);
@@ -229,9 +358,12 @@ void __ms_node_destroy(void *data)
        media_streamer_node_s *node = (media_streamer_node_s *)data;
        ms_retm_if(node == NULL, "Empty value while deleting element from table");
 
+       __ms_element_unlink(node->gst_element);
+
        node_name = g_strdup(node->name);
        MS_SAFE_UNREF(node->gst_element);
        MS_SAFE_FREE(node->name);
+       MS_SAFE_FREE(node->callbacks_structure);
 
        ms_info("Node [%s] destroyed", node_name);
        MS_SAFE_FREE(node_name);
@@ -262,6 +394,69 @@ int __ms_node_remove_from_table(GHashTable *nodes_table,
        return MEDIA_STREAMER_ERROR_NONE;
 }
 
+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");
+
+       /*Find unlinked element into 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);
+               } 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);
+
+               unlinked_pad = gst_bin_find_unlinked_pad(GST_BIN(ms_streamer->src_bin), GST_PAD_SRC);
+       }
+
+       return MEDIA_STREAMER_ERROR_NONE;
+}
+
 static void __params_foreach_cb(const char *key,
                                 const int type,
                                 const bundle_keyval_t *kv,
index 9c6f051..37b5ddb 100755 (executable)
@@ -47,6 +47,7 @@ int __ms_state_change(media_streamer_s *ms_streamer, media_streamer_state_e stat
                        }
                        break;
                case MEDIA_STREAMER_STATE_READY:
+                       ret = __ms_autoplug_prepare(ms_streamer);
                        break;
                case MEDIA_STREAMER_STATE_PLAYING:
                        ret = __ms_element_set_state(ms_streamer->pipeline, GST_STATE_PLAYING);
@@ -94,6 +95,7 @@ int __ms_create(media_streamer_s *ms_streamer)
        return ret;
 }
 
+#if 0
 static void __node_remove_cb(gpointer key,
                              gpointer value,
                              gpointer user_data)
@@ -137,7 +139,7 @@ static void __node_remove_cb(gpointer key,
        MS_SAFE_GFREE(bin_name);
 
 }
-
+#endif
 
 void __ms_streamer_destroy(media_streamer_s *ms_streamer)
 {
@@ -145,35 +147,24 @@ void __ms_streamer_destroy(media_streamer_s *ms_streamer)
                ms_error("Error: can not set state [%d]", MEDIA_STREAMER_ERROR_INVALID_OPERATION);
        }
 
-       gst_element_unlink_many(ms_streamer->src_bin,
-                               ms_streamer->topology_bin,
-                               ms_streamer->sink_video_bin, NULL);
-
-       g_hash_table_foreach(ms_streamer->nodes_table, __node_remove_cb, (gpointer)ms_streamer);
+       MS_TABLE_SAFE_UNREF(ms_streamer->nodes_table);
 
-       if (ms_streamer->src_bin && !gst_bin_remove(GST_BIN(ms_streamer->pipeline), ms_streamer->src_bin)) {
-               ms_error("Failed to remove src_bin from pipeline");
-       } else {
-               ms_info("src_bin removed from pipeline");
+       if (ms_streamer->sink_video_bin &&
+                       GST_OBJECT_PARENT(ms_streamer->sink_video_bin) != ms_streamer->pipeline) {
+               MS_SAFE_UNREF(ms_streamer->sink_video_bin);
+               ms_info("sink_video_bin removed from pipeline");
        }
 
-       if (ms_streamer->sink_video_bin && !gst_bin_remove(GST_BIN(ms_streamer->pipeline), ms_streamer->sink_video_bin)) {
-               ms_error("Failed to remove sink_bin from pipeline");
-       } else {
-               ms_info("sink_bin removed from pipeline");
+       if (ms_streamer->sink_audio_bin &&
+                       GST_OBJECT_PARENT(ms_streamer->sink_audio_bin) != ms_streamer->pipeline) {
+               MS_SAFE_UNREF(ms_streamer->sink_audio_bin);
+               ms_info("sink_audio_bin removed from pipeline");
        }
 
-
-       if (ms_streamer->topology_bin && !gst_bin_remove(GST_BIN(ms_streamer->pipeline), ms_streamer->topology_bin)) {
-               ms_error("Failed to remove topology_bin from pipeline");
-       } else {
-               ms_info("topology_bin removed from pipeline");
-       }
-
-
        ms_streamer->state = MEDIA_STREAMER_STATE_NONE;
+       g_mutex_unlock(&ms_streamer->mutex_lock);
+       g_mutex_clear(&ms_streamer->mutex_lock);
 
-       MS_TABLE_SAFE_UNREF(ms_streamer->nodes_table);
        MS_SAFE_UNREF(ms_streamer->bus);
        MS_SAFE_UNREF(ms_streamer->pipeline);
 
index 5e1520b..1cde4fc 100755 (executable)
@@ -192,4 +192,23 @@ const gchar *__ms_convert_mime_to_string(media_format_mimetype_e mime)
        }
 
 }
+
+media_format_mimetype_e __ms_convert_string_format_to_mime(const char *format_type)
+{
+       if (g_strrstr(format_type, "I420")) {
+               return MEDIA_FORMAT_I420;
+       } else if (g_strrstr(format_type, "YV12")) {
+               return MEDIA_FORMAT_YV12;
+       } else if (g_strrstr(format_type, "h263")) {
+               return MEDIA_FORMAT_H263;
+       } else if (g_strrstr(format_type, "h264")) {
+               return MEDIA_FORMAT_H264_SP;
+       } else if (g_strrstr(format_type, "S16BE")) {
+               return MEDIA_FORMAT_PCM;
+       } else {
+               ms_error("Invalid or Unsupported media format [%s].", format_type);
+               return MEDIA_FORMAT_NONE;
+       }
+}
+
 #endif
index 8eba035..2b979c3 100755 (executable)
@@ -173,14 +173,21 @@ static gboolean _destroy(media_streamer_h streamer)
                return FALSE;
        }
 
-       g_menu_preset = PRESET_UNKNOWN;
+
+       if (current_media_streamer == g_media_streamer) {
+               g_media_streamer = NULL;
+       } else {
+               g_media_streamer_2 = NULL;
+       }
+       current_media_streamer = NULL;
+
        g_print("== success destroy \n");
        return TRUE;
 }
 
 static void create_formats(void)
 {
-       if (!vfmt_raw || !vfmt_encoded || afmt_raw) {
+       if (!vfmt_raw || !vfmt_encoded || !afmt_raw) {
                g_print("Formats already created!");
        }
 
@@ -196,7 +203,7 @@ static void create_formats(void)
 
        /* Define encoded video format */
        media_format_create(&vfmt_encoded);
-       if (media_format_set_video_mime(vfmt_encoded, MEDIA_FORMAT_H264_SP) != MEDIA_FORMAT_ERROR_NONE) {
+       if (media_format_set_video_mime(vfmt_encoded, MEDIA_FORMAT_H263) != MEDIA_FORMAT_ERROR_NONE) {
                g_print("media_format_set_video_mime failed!");
        }
        media_format_set_video_width(vfmt_encoded, 800);
@@ -215,7 +222,7 @@ static void create_formats(void)
 }
 
 static void set_rtp_params(media_streamer_node_h rtp_node,
-                           const gchar *ip,
+                           const char *ip,
                            int video_port,
                            int audio_port,
                            gboolean port_reverse)
@@ -242,8 +249,8 @@ static void set_rtp_params(media_streamer_node_h rtp_node,
 #endif
 
 #ifndef DISABLE_VIDEO
-       gchar *video_src_port = g_strdup_printf("%d", port_reverse ? (video_port + 5) : video_port);
-       gchar *video_sink_port = g_strdup_printf("%d", port_reverse ? video_port : (video_port + 5));
+       char *video_src_port = g_strdup_printf("%d", port_reverse ? (video_port + 5) : video_port);
+       char *video_sink_port = g_strdup_printf("%d", port_reverse ? video_port : (video_port + 5));
 
        if (g_menu_preset & PRESET_RTP_STREAMER) {
                bundle_add_str(params, "video_sink,port", video_sink_port);
@@ -273,12 +280,13 @@ static gboolean _create_rtp_streamer(media_streamer_node_h rtp_bin)
        media_streamer_node_h video_src = NULL;
 #ifdef ONE_DEVICE_TEST
        if (g_menu_preset & SECOND_VOIP_MASK) {
-               media_streamer_src_create(MEDIA_STREAMER_SRC_TYPE_VIDEO_TEST, &video_src);
+               media_streamer_node_create_src(MEDIA_STREAMER_NODE_SRC_TYPE_VIDEO_TEST, &video_src);
+               media_streamer_node_set_param(video_src, "is-live", "true");
        } else {
-               media_streamer_src_create(MEDIA_STREAMER_SRC_TYPE_CAMERA, &video_src);
+               media_streamer_node_create_src(MEDIA_STREAMER_NODE_SRC_TYPE_CAMERA, &video_src);
        }
 #else
-       media_streamer_src_create(MEDIA_STREAMER_SRC_TYPE_CAMERA, &video_src);
+       media_streamer_node_create_src(MEDIA_STREAMER_NODE_SRC_TYPE_CAMERA, &video_src);
 #endif
        /*      media_streamer_node_set_fmt(video_src, vfmt_raw); */
        media_streamer_node_add(current_media_streamer, video_src);
@@ -306,7 +314,7 @@ static gboolean _create_rtp_streamer(media_streamer_node_h rtp_bin)
 #ifndef DISABLE_AUDIO
        /*********************** audiosrc *********************************** */
        media_streamer_node_h audio_src = NULL;
-       media_streamer_src_create(MEDIA_STREAMER_SRC_TYPE_AUDIO_CAPTURE, &audio_src);
+       media_streamer_node_create_src(MEDIA_STREAMER_NODE_SRC_TYPE_AUDIO_CAPTURE, &audio_src);
        media_streamer_node_add(current_media_streamer, audio_src);
 
        /*********************** audioencoder *********************************** */
@@ -332,6 +340,41 @@ static gboolean _create_rtp_streamer(media_streamer_node_h rtp_bin)
        return TRUE;
 }
 
+static gboolean _create_rtp_streamer_autoplug(media_streamer_node_h rtp_bin)
+{
+       g_print("== _create_rtp_streamer \n");
+
+#ifndef DISABLE_VIDEO
+       /*********************** video source *********************************** */
+       media_streamer_node_h video_src = NULL;
+#ifdef ONE_DEVICE_TEST
+       if (g_menu_preset & SECOND_VOIP_MASK) {
+               media_streamer_node_create_src(MEDIA_STREAMER_SRC_TYPE_VIDEO_TEST, &video_src);
+               media_streamer_node_set_single_param(video_src, "is-live", "true");
+       } else {
+               media_streamer_node_create_src(MEDIA_STREAMER_SRC_TYPE_CAMERA, &video_src);
+       }
+#else
+       media_streamer_node_create_src(MEDIA_STREAMER_NODE_SRC_TYPE_CAMERA, &video_src);
+#endif
+       /*      media_streamer_node_set_fmt(video_src, vfmt_raw); */
+       media_streamer_node_add(current_media_streamer, video_src);
+
+       g_print("== success streamer video part \n");
+#endif
+
+#ifndef DISABLE_AUDIO
+       /*********************** audiosrc *********************************** */
+       media_streamer_node_h audio_src = NULL;
+       media_streamer_node_create_src(MEDIA_STREAMER_NODE_SRC_TYPE_AUDIO_CAPTURE, &audio_src);
+       media_streamer_node_add(current_media_streamer, audio_src);
+
+       g_print("== success streamer audio part \n");
+#endif
+
+       return TRUE;
+}
+
 static gboolean _create_rtp_client(media_streamer_node_h rtp_bin)
 {
        g_print("== _create_rtp_client \n");
@@ -349,7 +392,7 @@ static gboolean _create_rtp_client(media_streamer_node_h rtp_bin)
 
        /*********************** videosink *********************************** */
        media_streamer_node_h video_sink = NULL;
-       media_streamer_sink_create(MEDIA_STREAMER_SINK_TYPE_SCREEN, &video_sink);
+       media_streamer_node_create_sink(MEDIA_STREAMER_NODE_SINK_TYPE_SCREEN, &video_sink);
        media_streamer_node_add(current_media_streamer, video_sink);
 
        /*====================Linking Video Client=========================== */
@@ -378,7 +421,7 @@ static gboolean _create_rtp_client(media_streamer_node_h rtp_bin)
 
        /*********************** audiosink *********************************** */
        media_streamer_node_h audio_sink = NULL;
-       media_streamer_sink_create(MEDIA_STREAMER_SINK_TYPE_AUDIO, &audio_sink);
+       media_streamer_node_create_sink(MEDIA_STREAMER_NODE_SINK_TYPE_AUDIO, &audio_sink);
        media_streamer_node_add(current_media_streamer, audio_sink);
 
        /*====================Linking Audio Client=========================== */
@@ -394,6 +437,32 @@ static gboolean _create_rtp_client(media_streamer_node_h rtp_bin)
        return TRUE;
 }
 
+static gboolean _create_rtp_client_autoplug(media_streamer_node_h rtp_bin)
+{
+       g_print("== _create_rtp_client \n");
+
+#ifndef DISABLE_VIDEO
+       /*********************** 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);
+
+       g_print("== success client video part \n");
+#endif
+
+#ifndef DISABLE_AUDIO
+       /*********************** 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);
+
+       g_print("== success client audio part \n");
+#endif
+
+       return TRUE;
+}
+
+
 static media_streamer_node_h _create_rtp(
     int video_port,
     int audio_port,
@@ -403,12 +472,83 @@ static media_streamer_node_h _create_rtp(
 
        /*********************** rtpbin *********************************** */
        media_streamer_node_h rtp_bin = NULL;
-       media_streamer_node_create(MEDIA_STREAMER_NODE_TYPE_RTP, vfmt_encoded, vfmt_encoded, &rtp_bin);
+       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);
        return rtp_bin;
 }
 
+/* Application source callback */
+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) {
+               g_print("Buffer status cb got underflow\n");
+
+               char *test = g_strdup_printf("[%d]This is buffer_status_cb test!", count);
+               guint64 size = strlen(test);
+
+               media_packet_h packet;
+               media_packet_create_from_external_memory(&vfmt_encoded,
+                               (void *)test, size, NULL, NULL, &packet);
+               media_streamer_node_push_packet(node, packet);
+               count++;
+       } else {
+               media_streamer_node_push_packet(node, NULL);
+               g_print("Buffer status cb got overflow\n");
+       }
+}
+
+/* Application sink callbacks */
+static void new_buffer_cb(media_streamer_node_h node, void *user_data)
+{
+       char *received_data = NULL;
+       media_packet_h packet;
+
+       media_streamer_node_pull_packet(node, &packet);
+       media_packet_get_buffer_data_ptr(packet, &received_data);
+       g_print("Received new packet from appsink with data [%s]\n", received_data);
+
+       media_packet_destroy(packet);
+}
+
+static void eos_cb(media_streamer_node_h node, void *user_data)
+{
+
+       g_print("Got EOS cb from appsink\n");
+}
+
+static gboolean _create_app_test()
+{
+       g_print("== _create_appsrc \n");
+
+       /*********************** app_src *********************************** */
+       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);
+
+       /*********************** 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);
+
+       /*====================Linking ======================================== */
+       media_streamer_node_link(app_src, "src", app_sink, "sink");
+       /*====================================================================== */
+
+       media_streamer_src_set_buffer_status_cb(app_src, buffer_status_cb, NULL);
+       media_streamer_sink_set_data_ready_cb(app_sink, new_buffer_cb, NULL);
+       media_streamer_sink_set_eos_cb(app_sink, eos_cb, NULL);
+
+       g_print("== success appsrc part \n");
+
+       return TRUE;
+}
+
 /***************************************************************/
 /**  Testsuite */
 /***************************************************************/
@@ -488,8 +628,8 @@ static void display_voip_menu(void)
        g_print("1. one streamer VoIP 1 \n");
        g_print("2. one streamer VoIP 2 \n");
        g_print("3. two streamers VoIP server 1 \n");
-       g_print("4. two streamers VoIP server 2 \n");
-       g_print("5. two streamers VoIP client 1 \n");
+       g_print("4. two streamers VoIP client 1 \n");
+       g_print("5. two streamers VoIP server 2 \n");
        g_print("6. two streamers VoIP client 2 \n");
        g_print("b. back \n");
        g_print("----------------------------------------------------\n");
@@ -569,11 +709,19 @@ static void run_preset(void)
        switch (g_menu_preset) {
                case PRESET_RTP_STREAMER:
                        rtp_bin = _create_rtp(VIDEO_PORT, AUDIO_PORT, FALSE);
-                       _create_rtp_streamer(rtp_bin);
+                       if (g_autoplug_mode) {
+                               _create_rtp_streamer_autoplug(rtp_bin);
+                       } else {
+                               _create_rtp_streamer(rtp_bin);
+                       }
                        break;
                case PRESET_RTP_CLIENT:
                        rtp_bin = _create_rtp(VIDEO_PORT, AUDIO_PORT, TRUE);
-                       _create_rtp_client(rtp_bin);
+                       if (g_autoplug_mode) {
+                               _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);
@@ -661,13 +809,13 @@ void _interpret_voip_menu(char *cmd)
                        g_menu_preset = PRESET_DOUBLE_VOIP_SERVER;
                        g_menu_state = MENU_STATE_PRESET_MENU;
                } else if (!strncmp(cmd, "4", len)) {
-                       /*double Server 2 */
-                       g_menu_preset = PRESET_DOUBLE_VOIP_SERVER_2;
-                       g_menu_state = MENU_STATE_PRESET_MENU;
-               } else if (!strncmp(cmd, "5", len)) {
                        /*double Client 1 */
                        g_menu_preset = PRESET_DOUBLE_VOIP_CLIENT;
                        g_menu_state = MENU_STATE_PRESET_MENU;
+               } else if (!strncmp(cmd, "5", len)) {
+                       /*double Server 2 */
+                       g_menu_preset = PRESET_DOUBLE_VOIP_SERVER_2;
+                       g_menu_state = MENU_STATE_PRESET_MENU;
                } else if (!strncmp(cmd, "6", len)) {
                        /*double Client 2 */
                        g_menu_preset = PRESET_DOUBLE_VOIP_CLIENT_2;
@@ -752,7 +900,6 @@ void _interpret_preset_menu(char *cmd)
                        _play(g_media_streamer);
                } else if (!strncmp(cmd, "7", len)) {
                        _destroy(current_media_streamer);
-                       current_media_streamer = NULL;
                } else if (!strncmp(cmd, "b", len)) {
                        if (g_menu_preset & DOUBLE_STREAMER_MASK) {
                                g_menu_state = MENU_STATE_VOIP_MENU;