From 4c828d03e9d7e4e029f54231a8b9ce49cfccd7fc Mon Sep 17 00:00:00 2001 From: Volodymyr Brynza Date: Thu, 9 Jun 2016 12:00:52 +0300 Subject: [PATCH] Modified Mediastreamer State Change Change-Id: I4a2ac52963faeb727a4bfee45590648273ee33bb Signed-off-by: Volodymyr Brynza --- include/media_streamer_node.h | 6 ++++++ include/media_streamer_priv.h | 1 + include/media_streamer_util.h | 1 - src/media_streamer.c | 22 +++++++++++----------- src/media_streamer_gst.c | 33 ++++++++++++++++++++++++++++++--- src/media_streamer_node.c | 35 ++++++++++++++++++++++++++++++++--- src/media_streamer_priv.c | 29 ++++++++++++----------------- test/media_streamer_test.c | 7 +++++++ 8 files changed, 99 insertions(+), 35 deletions(-) diff --git a/include/media_streamer_node.h b/include/media_streamer_node.h index d68ec71..eb89d8c 100644 --- a/include/media_streamer_node.h +++ b/include/media_streamer_node.h @@ -16,6 +16,12 @@ #include +/** + * @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. diff --git a/include/media_streamer_priv.h b/include/media_streamer_priv.h index c930c6c..c559c1a 100755 --- a/include/media_streamer_priv.h +++ b/include/media_streamer_priv.h @@ -105,6 +105,7 @@ typedef struct { 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; diff --git a/include/media_streamer_util.h b/include/media_streamer_util.h index 7377677..3079de5 100644 --- a/include/media_streamer_util.h +++ b/include/media_streamer_util.h @@ -223,7 +223,6 @@ typedef struct { #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) \ diff --git a/src/media_streamer.c b/src/media_streamer.c index 1016f9d..c3cf041 100644 --- a/src/media_streamer.c +++ b/src/media_streamer.c @@ -190,16 +190,12 @@ int media_streamer_prepare(media_streamer_h streamer) 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; } @@ -215,10 +211,7 @@ int media_streamer_unprepare(media_streamer_h streamer) __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"); @@ -241,6 +234,8 @@ int media_streamer_play(media_streamer_h streamer) g_mutex_unlock(&ms_streamer->mutex_lock); + __ms_get_state(ms_streamer); + return ret; } @@ -264,7 +259,8 @@ int media_streamer_create(media_streamer_h *streamer) 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"); @@ -454,6 +450,8 @@ int media_streamer_pause(media_streamer_h streamer) g_mutex_unlock(&ms_streamer->mutex_lock); + __ms_get_state(ms_streamer); + return ret; } @@ -476,6 +474,8 @@ int media_streamer_stop(media_streamer_h streamer) g_mutex_unlock(&ms_streamer->mutex_lock); + __ms_get_state(ms_streamer); + return ret; } diff --git a/src/media_streamer_gst.c b/src/media_streamer_gst.c index f83e993..423fd24 100755 --- a/src/media_streamer_gst.c +++ b/src/media_streamer_gst.c @@ -1346,11 +1346,31 @@ static gboolean __ms_bus_cb(GstBus *bus, GstMessage *message, gpointer userdata) 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; } @@ -1359,14 +1379,21 @@ static gboolean __ms_bus_cb(GstBus *bus, GstMessage *message, gpointer userdata) 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; } diff --git a/src/media_streamer_node.c b/src/media_streamer_node.c index 2f55ed2..03ecab8 100755 --- a/src/media_streamer_node.c +++ b/src/media_streamer_node.c @@ -79,6 +79,16 @@ node_info_s nodes_info[] = { {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"); @@ -481,14 +491,31 @@ int __ms_pipeline_prepare(media_streamer_s *ms_streamer) { 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) @@ -542,6 +569,8 @@ int __ms_pipeline_unprepare(media_streamer_s *ms_streamer) 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); diff --git a/src/media_streamer_priv.c b/src/media_streamer_priv.c index 00e7e16..47dd4bb 100644 --- a/src/media_streamer_priv.c +++ b/src/media_streamer_priv.c @@ -26,9 +26,7 @@ int __ms_state_change(media_streamer_s *ms_streamer, media_streamer_state_e stat 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: @@ -36,27 +34,31 @@ int __ms_state_change(media_streamer_s *ms_streamer, media_streamer_state_e stat * 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:{ @@ -65,13 +67,6 @@ int __ms_state_change(media_streamer_s *ms_streamer, media_streamer_state_e stat } } - 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; } diff --git a/test/media_streamer_test.c b/test/media_streamer_test.c index a285add..09c6b1b 100644 --- a/test/media_streamer_test.c +++ b/test/media_streamer_test.c @@ -142,6 +142,11 @@ static void streamer_seek_cb(void *user_data) 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"); @@ -170,6 +175,8 @@ static void _prepare(void) 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"); } -- 2.7.4