#include <media_streamer_priv.h>
+/**
+ * @brief Gets state of media streamer.
+ *
+ * @since_tizen 3.0
+ */
+void __ms_get_state(media_streamer_s *ms_streamer);
/**
* @brief Creates media streamer node using input and output format.
gboolean is_seeking;
media_streamer_state_e state;
+ media_streamer_state_e pend_state;
media_streamer_callback_s error_cb;
media_streamer_callback_s state_changed_cb;
#define MS_BIN_UNPREPARE(bin) \
if (!__ms_bin_remove_elements(ms_streamer, bin)) {\
ms_debug("Got a few errors during unprepare [%s] bin.", GST_ELEMENT_NAME(bin));\
- ret = MEDIA_STREAMER_ERROR_INVALID_OPERATION;\
}
#define MS_SET_INT_RTP_PARAM(obj, key, value) \
ret = __ms_pipeline_prepare(ms_streamer);
- if (ret == MEDIA_STREAMER_ERROR_NONE) {
- ret = __ms_state_change(ms_streamer, MEDIA_STREAMER_STATE_READY);
- if (ret != MEDIA_STREAMER_ERROR_NONE)
- __ms_pipeline_unprepare(ms_streamer);
- }
-
__ms_generate_dots(ms_streamer->pipeline, "after_prepare");
g_mutex_unlock(&ms_streamer->mutex_lock);
+ __ms_get_state(ms_streamer);
+
return ret;
}
__ms_generate_dots(ms_streamer->pipeline, "before_unprepare");
- ret = __ms_state_change(ms_streamer, MEDIA_STREAMER_STATE_IDLE);
-
- if (ret == MEDIA_STREAMER_ERROR_NONE)
- ret = __ms_pipeline_unprepare(ms_streamer);
+ ret = __ms_pipeline_unprepare(ms_streamer);
__ms_generate_dots(ms_streamer->pipeline, "after_unprepare");
g_mutex_unlock(&ms_streamer->mutex_lock);
+ __ms_get_state(ms_streamer);
+
return ret;
}
return ret;
}
- ms_streamer->state = MEDIA_STREAMER_STATE_IDLE;
+ ms_streamer->pend_state = MEDIA_STREAMER_STATE_NONE;
+ ret = __ms_state_change(ms_streamer, MEDIA_STREAMER_STATE_IDLE);
*streamer = ms_streamer;
ms_info("Media Streamer created successfully");
g_mutex_unlock(&ms_streamer->mutex_lock);
+ __ms_get_state(ms_streamer);
+
return ret;
}
g_mutex_unlock(&ms_streamer->mutex_lock);
+ __ms_get_state(ms_streamer);
+
return ret;
}
gchar *state_transition_name;
gst_message_parse_state_changed(message, &state_old, &state_new, &state_pending);
- state_transition_name = g_strdup_printf("%s_%s", gst_element_state_get_name(state_old), gst_element_state_get_name(state_new));
- ms_info("GST_MESSAGE_STATE_CHANGED: [%s] %s", GST_OBJECT_NAME(GST_MESSAGE_SRC(message)), state_transition_name);
+ state_transition_name = g_strdup_printf("Old_[%s]_New_[%s]_Pending_[%s]", gst_element_state_get_name(state_old),
+ gst_element_state_get_name(state_new), gst_element_state_get_name(state_pending));
+ ms_info("GST_MESSAGE_STATE_CHANGED: [%s] %s. ", GST_OBJECT_NAME(GST_MESSAGE_SRC(message)), state_transition_name);
__ms_generate_dots(ms_streamer->pipeline, state_transition_name);
-
MS_SAFE_GFREE(state_transition_name);
+
+ media_streamer_state_e old_state = ms_streamer->state;
+ if (state_new >= GST_STATE_PAUSED)
+ {
+ if ((old_state == MEDIA_STREAMER_STATE_PLAYING) && (state_new <= GST_STATE_PAUSED))
+ ms_streamer->pend_state = MEDIA_STREAMER_STATE_PAUSED;
+
+ if (ms_streamer->pend_state != ms_streamer->state) {
+
+ g_mutex_lock(&ms_streamer->mutex_lock);
+ ms_streamer->state = ms_streamer->pend_state;
+ g_mutex_unlock(&ms_streamer->mutex_lock);
+
+ ms_info("Media streamer state changed to [%d] [%d]", old_state, ms_streamer->state);
+ if (ms_streamer->state_changed_cb.callback) {
+ media_streamer_state_changed_cb cb = (media_streamer_state_changed_cb) ms_streamer->state_changed_cb.callback;
+ cb((media_streamer_h) ms_streamer, old_state, ms_streamer->state, ms_streamer->state_changed_cb.user_data);
+ }
+ }
+ }
}
break;
}
if (GST_MESSAGE_SRC(message) == GST_OBJECT(ms_streamer->pipeline)
&& ms_streamer->is_seeking) {
+ g_mutex_lock(&ms_streamer->mutex_lock);
+ ms_streamer->pend_state = MEDIA_STREAMER_STATE_SEEKING;
+ g_mutex_unlock(&ms_streamer->mutex_lock);
+
if (ms_streamer->seek_done_cb.callback) {
media_streamer_position_changed_cb cb = (media_streamer_position_changed_cb) ms_streamer->seek_done_cb.callback;
cb(ms_streamer->seek_done_cb.user_data);
}
+ g_mutex_lock(&ms_streamer->mutex_lock);
ms_streamer->is_seeking = FALSE;
+ ms_streamer->pend_state = MEDIA_STREAMER_STATE_PLAYING;
ms_streamer->seek_done_cb.callback = NULL;
ms_streamer->seek_done_cb.user_data = NULL;
+ g_mutex_unlock(&ms_streamer->mutex_lock);
}
break;
}
{NULL, NULL}
};
+void __ms_get_state(media_streamer_s *ms_streamer)
+{
+ GstState state_old, state_new;
+ GstStateChangeReturn ret_state = gst_element_get_state(ms_streamer->pipeline, &state_old, &state_new, GST_CLOCK_TIME_NONE);
+ if (ret_state == GST_STATE_CHANGE_SUCCESS)
+ ms_info("Got state for [%s]: old [%s], new [%s]", GST_ELEMENT_NAME(ms_streamer->pipeline), gst_element_state_get_name(state_old), gst_element_state_get_name(state_new));
+ else
+ ms_error("Couldn`t get state for [%s]", GST_ELEMENT_NAME(ms_streamer->pipeline));
+}
+
static gboolean __ms_rtp_node_has_property(media_streamer_node_s *ms_node, const gchar *param_name)
{
ms_retvm_if(!ms_node || !ms_node->gst_element, FALSE, "Error: empty node");
{
ms_retvm_if(ms_streamer == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+ int ret = MEDIA_STREAMER_ERROR_NONE;
media_streamer_node_s *rtp_node = (media_streamer_node_s *)g_hash_table_lookup(ms_streamer->nodes_table, "rtp_container");
- if (rtp_node)
- __ms_rtp_element_prepare(rtp_node);
+ if (rtp_node) {
+ ret = __ms_rtp_element_prepare(rtp_node) ? MEDIA_STREAMER_ERROR_NONE : MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
+ } else {
+ GstBin *nodes_bin = GST_BIN(ms_streamer->src_bin);
+ if(nodes_bin->numchildren == 0) {
+ ms_debug(" No any node is added to [%s]", GST_ELEMENT_NAME(ms_streamer->src_bin));
+ return MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
+ }
+ nodes_bin = GST_BIN(ms_streamer->sink_bin);
+ if(nodes_bin->numchildren == 0) {
+ ms_debug(" No any node is added to [%s]", GST_ELEMENT_NAME(ms_streamer->sink_bin));
+ return MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
+ }
+ }
MS_BIN_FOREACH_ELEMENTS(ms_streamer->sink_bin, __ms_element_lock_state, ms_streamer);
MS_BIN_FOREACH_ELEMENTS(ms_streamer->src_bin, _src_node_prepare, ms_streamer);
- return MEDIA_STREAMER_ERROR_NONE;
+ ret = __ms_state_change(ms_streamer, MEDIA_STREAMER_STATE_READY);
+ if (ret != MEDIA_STREAMER_ERROR_NONE)
+ __ms_pipeline_unprepare(ms_streamer);
+
+ return ret;
}
static gboolean __ms_bin_remove_elements(media_streamer_s *ms_streamer, GstElement *bin)
int ret = MEDIA_STREAMER_ERROR_NONE;
__ms_element_set_state(ms_streamer->pipeline, GST_STATE_NULL);
+ ms_streamer->state = MEDIA_STREAMER_STATE_IDLE;
+ ms_streamer->pend_state = ms_streamer->state;
MS_BIN_FOREACH_ELEMENTS(ms_streamer->sink_bin, __ms_element_unlock_state, ms_streamer);
int ret = MEDIA_STREAMER_ERROR_NONE;
ms_retvm_if(ms_streamer == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Handle is NULL");
-
- media_streamer_state_e previous_state = ms_streamer->state;
- ms_retvm_if(previous_state == state, MEDIA_STREAMER_ERROR_NONE, "Media streamer already in this state");
+ ms_retvm_if(ms_streamer->state == state, MEDIA_STREAMER_ERROR_NONE, "Media streamer already in this state");
switch (state) {
case MEDIA_STREAMER_STATE_NONE:
* Media streamer must be in IDLE state
* Unlink and destroy all bins and elements.
*/
- if (previous_state != MEDIA_STREAMER_STATE_IDLE)
- __ms_state_change(ms_streamer, MEDIA_STREAMER_STATE_IDLE);
+ ret = __ms_element_set_state(ms_streamer->pipeline, GST_STATE_NULL);
+ ms_streamer->pend_state = 0;
+ ms_streamer->state = state;
break;
case MEDIA_STREAMER_STATE_IDLE:
/*
* Unlink all gst_elements, set pipeline into state NULL
*/
- if (previous_state != MEDIA_STREAMER_STATE_NONE) {
- MS_BIN_FOREACH_ELEMENTS(ms_streamer->sink_bin, __ms_element_unlock_state, ms_streamer);
- ret = __ms_element_set_state(ms_streamer->pipeline, GST_STATE_NULL);
- }
+ ret = __ms_element_set_state(ms_streamer->pipeline, GST_STATE_NULL);
+ MS_BIN_FOREACH_ELEMENTS(ms_streamer->sink_bin, __ms_element_unlock_state, ms_streamer);
+ ms_streamer->pend_state = MEDIA_STREAMER_STATE_NONE;
+ ms_streamer->state = state;
break;
case MEDIA_STREAMER_STATE_READY:
ret = __ms_element_set_state(ms_streamer->pipeline, GST_STATE_PAUSED);
+ ms_streamer->pend_state = MEDIA_STREAMER_STATE_READY;
break;
case MEDIA_STREAMER_STATE_PLAYING:
- MS_BIN_FOREACH_ELEMENTS(ms_streamer->sink_bin, __ms_element_unlock_state, ms_streamer);
ret = __ms_element_set_state(ms_streamer->pipeline, GST_STATE_PLAYING);
+ MS_BIN_FOREACH_ELEMENTS(ms_streamer->sink_bin, __ms_element_unlock_state, ms_streamer);
+ ms_streamer->pend_state = MEDIA_STREAMER_STATE_PLAYING;
break;
case MEDIA_STREAMER_STATE_PAUSED:
ret = __ms_element_set_state(ms_streamer->pipeline, GST_STATE_PAUSED);
+ ms_streamer->pend_state = MEDIA_STREAMER_STATE_PAUSED;
break;
case MEDIA_STREAMER_STATE_SEEKING:
default:{
}
}
- if (ret != MEDIA_STREAMER_ERROR_NONE) {
- ms_error("Failed change state");
- return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
- }
-
- ms_streamer->state = state;
- ms_info("Media streamer state changed to [%d]", state);
return ret;
}
g_print("Current play position [%02d:%02d:%03d] \n", current_time / (1000 * 60), (current_time / 1000) % 60, current_time % 1000);
}
+static void streamer_changed_cb(media_streamer_h streamer, media_streamer_state_e previous_state, media_streamer_state_e current_state, void *user_data)
+{
+ g_print("Media Streamer State changed [%d] -> [%d]", previous_state, current_state);
+}
+
static void _create(media_streamer_h *streamer)
{
g_print("== create \n");
g_print("Fail to prepare media streamer");
return;
}
+
+ media_streamer_set_state_change_cb(current_media_streamer, streamer_changed_cb, NULL);
g_print("== success prepare \n");
}