#include <tizen.h>
#include <bundle.h>
-#include <mm_message.h>
#include <media_format.h>
#include <media_packet.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 */
* @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.
* @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.
* @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
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
* @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,
/**
* @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()
*/
/**
* @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()
*/
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
* @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
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
* @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
/**
* @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
* @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()
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
* @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()
* @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.
* @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()
* @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
* @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()
/**
* @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,
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,
* @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);
/**
* @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
* @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
/**
* @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,
* @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
* @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,
* @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
* @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
* @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);
* @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,
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
* @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
* @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.
* @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);
/**
* @}
*
* @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.
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.
*
* @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.
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);
* @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.
* @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.
* @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);
} 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
*
* @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.
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;
} 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"
/* 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 \
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
* 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;
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);
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;
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);
/* 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)
{
ms_error("Error creating Media Streamer");
__ms_streamer_destroy(ms_streamer);
- g_mutex_clear(&ms_streamer->mutex_lock);
-
return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
}
__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;
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;
}
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;
}
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;
}
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;
}
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;
}
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;
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;
}
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;
}
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");
*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;
+}
+
#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;
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);
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;
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)) {
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;
}
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)
{
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;
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);
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)
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);
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);
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;
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;
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;
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;
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;
+}
#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)
__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));
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);
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)
{
__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);
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");
__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);
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);
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,
}
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);
return ret;
}
+#if 0
static void __node_remove_cb(gpointer key,
gpointer value,
gpointer user_data)
MS_SAFE_GFREE(bin_name);
}
-
+#endif
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);
}
}
+
+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
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!");
}
/* 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);
}
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)
#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);
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);
#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 *********************************** */
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");
/*********************** 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=========================== */
/*********************** 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=========================== */
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,
/*********************** 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 */
/***************************************************************/
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");
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);
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;
_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;