From 06328bf46c0b55a1bc21641ba408a6913a4d453c Mon Sep 17 00:00:00 2001 From: Eunhye Choi Date: Mon, 14 Oct 2019 17:21:50 +0900 Subject: [PATCH] [0.6.207] use reconfigure lock to sync operation - use reconfigure lock for reconfig state - check reconfigure state before starting the playback related function. - release uri list mem during player destroy - enlarge the default number of bo to consider the web requirement Change-Id: I32b6363476f000be136072bce5b77fa7747fe4d6 --- packaging/libmm-player.spec | 2 +- src/include/mm_player_priv.h | 6 ++- src/include/mm_player_utils.h | 8 +-- src/mm_player.c | 16 +++--- src/mm_player_gst.c | 4 +- src/mm_player_priv.c | 100 ++++++++++++++++++++++---------------- unittest/gtest_mm_player_priv.cpp | 11 +++-- 7 files changed, 84 insertions(+), 63 deletions(-) diff --git a/packaging/libmm-player.spec b/packaging/libmm-player.spec index b8eed46..67e6699 100644 --- a/packaging/libmm-player.spec +++ b/packaging/libmm-player.spec @@ -1,6 +1,6 @@ Name: libmm-player Summary: Multimedia Framework Player Library -Version: 0.6.206 +Version: 0.6.207 Release: 0 Group: Multimedia/Libraries License: Apache-2.0 diff --git a/src/include/mm_player_priv.h b/src/include/mm_player_priv.h index 5431dfd..25c944c 100644 --- a/src/include/mm_player_priv.h +++ b/src/include/mm_player_priv.h @@ -70,7 +70,7 @@ #define VIDEO360_MAX_ZOOM 10.0f -#define DEFAULT_NUM_OF_V_OUT_BUFFER 3 +#define DEFAULT_NUM_OF_V_OUT_BUFFER 4 /*--------------------------------------------------------------------------- | GLOBAL CONSTANT DEFINITIONS: | @@ -537,7 +537,8 @@ typedef struct { /* command lock */ GMutex cmd_lock; - GMutex playback_lock; + GMutex reconfigure_lock; + GCond reconfigure_cond; /* gapless play thread */ GThread *gapless_play_thread; @@ -889,6 +890,7 @@ int _mmplayer_gst_element_link_bucket(GList *element_bucket); void _mmplayer_typefind_have_type(GstElement *tf, guint probability, GstCaps *caps, gpointer data); int _mmplayer_parse_profile(const char *uri, void *param, mmplayer_parse_profile_t *data); int _mmplayer_set_client_pid(MMHandleType hplayer, int pid); +void _mmplayer_set_reconfigure_state(mmplayer_t *player, gboolean state); #ifdef __cplusplus } diff --git a/src/include/mm_player_utils.h b/src/include/mm_player_utils.h index b0f9630..4f12889 100644 --- a/src/include/mm_player_utils.h +++ b/src/include/mm_player_utils.h @@ -64,9 +64,11 @@ #define MMPLAYER_CMD_TRYLOCK(x_player) g_mutex_trylock(&((mmplayer_t *)x_player)->cmd_lock) #define MMPLAYER_CMD_UNLOCK(x_player) g_mutex_unlock(&((mmplayer_t *)x_player)->cmd_lock) -/* playback */ -#define MMPLAYER_PLAYBACK_LOCK(x_player) g_mutex_lock(&((mmplayer_t *)x_player)->playback_lock) -#define MMPLAYER_PLAYBACK_UNLOCK(x_player) g_mutex_unlock(&((mmplayer_t *)x_player)->playback_lock) +/* pipeline reconfigure */ +#define MMPLAYER_RECONFIGURE_LOCK(x_player) g_mutex_lock(&((mmplayer_t *)x_player)->reconfigure_lock) +#define MMPLAYER_RECONFIGURE_UNLOCK(x_player) g_mutex_unlock(&((mmplayer_t *)x_player)->reconfigure_lock) +#define MMPLAYER_RECONFIGURE_WAIT(x_player) g_cond_wait(&((mmplayer_t *)x_player)->reconfigure_cond, &((mmplayer_t *)x_player)->reconfigure_lock) +#define MMPLAYER_RECONFIGURE_SIGNAL(x_player) g_cond_signal(&((mmplayer_t *)x_player)->reconfigure_cond); /* capture thread */ #define MMPLAYER_CAPTURE_THREAD_LOCK(x_player) g_mutex_lock(&((mmplayer_t *)x_player)->capture_thread_mutex) diff --git a/src/mm_player.c b/src/mm_player.c index 4134c2f..bcd2d7d 100644 --- a/src/mm_player.c +++ b/src/mm_player.c @@ -53,11 +53,10 @@ int mm_player_create(MMHandleType *player) goto ERROR; } - /* create player cmd lock */ + /* create player lock and cond */ g_mutex_init(&new_player->cmd_lock); - - /* create player playback lock */ - g_mutex_init(&new_player->playback_lock); + g_mutex_init(&new_player->reconfigure_lock); + g_cond_init(&new_player->reconfigure_cond); /* load ini files */ if (MM_ERROR_NONE != mm_player_ini_load(&new_player->ini)) { @@ -88,8 +87,8 @@ ERROR: if (new_player) { _mmplayer_destroy((MMHandleType)new_player); g_mutex_clear(&new_player->cmd_lock); - g_mutex_clear(&new_player->playback_lock); - + g_mutex_clear(&new_player->reconfigure_lock); + g_cond_clear(&new_player->reconfigure_cond); MMPLAYER_FREEIF(new_player); } @@ -114,7 +113,8 @@ int mm_player_destroy(MMHandleType player) MMPLAYER_CMD_UNLOCK(player); g_mutex_clear(&((mmplayer_t *)player)->cmd_lock); - g_mutex_clear(&((mmplayer_t *)player)->playback_lock); + g_mutex_clear(&((mmplayer_t *)player)->reconfigure_lock); + g_cond_clear(&((mmplayer_t *)player)->reconfigure_cond); memset((mmplayer_t *)player, 0x00, sizeof(mmplayer_t)); @@ -1276,4 +1276,4 @@ int mm_player_is_audio_control_available(MMHandleType player, mmplayer_audio_con MMPLAYER_CMD_UNLOCK(player); return result; -} \ No newline at end of file +} diff --git a/src/mm_player_gst.c b/src/mm_player_gst.c index edd913d..25b1cd9 100644 --- a/src/mm_player_gst.c +++ b/src/mm_player_gst.c @@ -1922,6 +1922,7 @@ __mmplayer_gst_bus_msg_callback(GstMessage *msg, gpointer data) break; case GST_MESSAGE_ERROR: + _mmplayer_set_reconfigure_state(player, FALSE); __mmplayer_gst_handle_error_message(player, msg); break; @@ -4056,8 +4057,7 @@ _mmplayer_activate_next_source(mmplayer_t *player, GstState target) ERROR: if (player) { - MMPLAYER_PLAYBACK_UNLOCK(player); - + _mmplayer_set_reconfigure_state(player, FALSE); if (!player->msg_posted) { MMPLAYER_POST_MSG(player, MM_MESSAGE_ERROR, &msg_param); player->msg_posted = TRUE; diff --git a/src/mm_player_priv.c b/src/mm_player_priv.c index 6f1a7d6..1c585c3 100644 --- a/src/mm_player_priv.c +++ b/src/mm_player_priv.c @@ -178,7 +178,7 @@ static int __mmplayer_gst_set_message_callback(mmplayer_t *player, MMMessageCal /* util */ static gboolean __mmplayer_verify_gapless_play_path(mmplayer_t *player); -static void __mmplayer_check_pipeline(mmplayer_t *player); +static void __mmplayer_check_pipeline_reconfigure_state(mmplayer_t *player); static gboolean __mmplayer_deactivate_selector(mmplayer_t *player, mmplayer_track_type_e type); static void __mmplayer_deactivate_old_path(mmplayer_t *player); static int __mmplayer_gst_create_plain_text_elements(mmplayer_t *player); @@ -690,6 +690,16 @@ __mmplayer_initialize_gapless_play(mmplayer_t *player) MMPLAYER_FLEAVE(); } +void _mmplayer_set_reconfigure_state(mmplayer_t *player, gboolean state) +{ + LOGI("set pipeline reconfigure state %d", state); + MMPLAYER_RECONFIGURE_LOCK(player); + player->gapless.reconfigure = state; + if (!state) /* wake up the waiting job */ + MMPLAYER_RECONFIGURE_SIGNAL(player); + MMPLAYER_RECONFIGURE_UNLOCK(player); +} + static gpointer __mmplayer_gapless_play_thread(gpointer data) { @@ -706,10 +716,7 @@ __mmplayer_gapless_play_thread(gpointer data) LOGD("reconfigure pipeline for gapless play."); if (player->gapless_play_thread_exit) { - if (player->gapless.reconfigure) { - player->gapless.reconfigure = false; - MMPLAYER_PLAYBACK_UNLOCK(player); - } + _mmplayer_set_reconfigure_state(player, FALSE); LOGD("exiting gapless play thread"); break; } @@ -1512,11 +1519,7 @@ __mmplayer_gst_decode_no_more_pads(GstElement *elem, gpointer data) __mmplayer_create_text_sink_path(player, text_selector); EXIT: - if (player->gapless.reconfigure) { - player->gapless.reconfigure = FALSE; - MMPLAYER_PLAYBACK_UNLOCK(player); - } - + _mmplayer_set_reconfigure_state(player, FALSE); MMPLAYER_FLEAVE(); } @@ -4202,7 +4205,9 @@ __mmplayer_gst_destroy_pipeline(mmplayer_t *player) player->subtitle_language_list = NULL; MMPLAYER_SUBTITLE_INFO_UNLOCK(player); + MMPLAYER_RECONFIGURE_LOCK(player); __mmplayer_reset_gapless_state(player); + MMPLAYER_RECONFIGURE_UNLOCK(player); if (player->streamer) { _mm_player_streaming_initialize(player->streamer, FALSE); @@ -4928,6 +4933,16 @@ _mmplayer_destroy(MMHandleType handle) /* release attributes */ _mmplayer_deconstruct_attribute(handle); + if (player->uri_info.uri_list) { + GList *uri_list = player->uri_info.uri_list; + for (; uri_list; uri_list = g_list_next(uri_list)) { + gchar *uri = uri_list->data; + MMPLAYER_FREEIF(uri); + } + g_list_free(player->uri_info.uri_list); + player->uri_info.uri_list = NULL; + } + /* release lock */ g_mutex_clear(&player->fsink_lock); @@ -5429,28 +5444,32 @@ __mmplayer_handle_missed_plugin(mmplayer_t *player) return MM_ERROR_NONE; } -static void -__mmplayer_check_pipeline(mmplayer_t *player) +static void __mmplayer_check_pipeline_reconfigure_state(mmplayer_t *player) { GstState element_state = GST_STATE_VOID_PENDING; GstState element_pending_state = GST_STATE_VOID_PENDING; - gint timeout = 0; - int ret = MM_ERROR_NONE; + GstStateChangeReturn result = GST_STATE_CHANGE_FAILURE; + gint timeout = MMPLAYER_STATE_CHANGE_TIMEOUT(player); + + MMPLAYER_RETURN_IF_FAIL(player && player->pipeline); - if (!player->gapless.reconfigure) + MMPLAYER_RECONFIGURE_LOCK(player); + if (!player->gapless.reconfigure) { + MMPLAYER_RECONFIGURE_UNLOCK(player); return; + } - LOGW("pipeline is under construction."); + LOGI("reconfigure is under process"); + MMPLAYER_RECONFIGURE_WAIT(player); + MMPLAYER_RECONFIGURE_UNLOCK(player); + LOGI("reconfigure is completed."); - MMPLAYER_PLAYBACK_LOCK(player); - MMPLAYER_PLAYBACK_UNLOCK(player); + result = gst_element_get_state(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, + &element_state, &element_pending_state, timeout * GST_SECOND); + if (result == GST_STATE_CHANGE_FAILURE) + LOGW("failed to get pipeline state in %d sec", timeout); - timeout = MMPLAYER_STATE_CHANGE_TIMEOUT(player); - - /* wait for state transition */ - ret = gst_element_get_state(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, &element_state, &element_pending_state, timeout * GST_SECOND); - if (ret == GST_STATE_CHANGE_FAILURE) - LOGE("failed to change pipeline state within %d sec", timeout); + return; } /* NOTE : it should be able to call 'stop' anytime*/ @@ -5467,9 +5486,11 @@ _mmplayer_stop(MMHandleType hplayer) /* check current state */ MMPLAYER_CHECK_STATE(player, MMPLAYER_COMMAND_STOP); - /* check pipline building state */ - __mmplayer_check_pipeline(player); + /* need to wait till the rebuilding pipeline is completed */ + __mmplayer_check_pipeline_reconfigure_state(player); + MMPLAYER_RECONFIGURE_LOCK(player); __mmplayer_reset_gapless_state(player); + MMPLAYER_RECONFIGURE_UNLOCK(player); /* NOTE : application should not wait for EOS after calling STOP */ _mmplayer_cancel_eos_timer(player); @@ -5503,8 +5524,8 @@ _mmplayer_pause(MMHandleType hplayer) /* check current state */ MMPLAYER_CHECK_STATE(player, MMPLAYER_COMMAND_PAUSE); - /* check pipline building state */ - __mmplayer_check_pipeline(player); + /* check pipline reconfigure state */ + __mmplayer_check_pipeline_reconfigure_state(player); switch (MMPLAYER_CURRENT_STATE(player)) { case MM_PLAYER_STATE_READY: @@ -5711,8 +5732,8 @@ _mmplayer_set_position(MMHandleType hplayer, gint64 position) MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED); - /* check pipline building state */ - __mmplayer_check_pipeline(player); + /* check pipline reconfigure state */ + __mmplayer_check_pipeline_reconfigure_state(player); ret = _mmplayer_gst_set_position(player, position, FALSE); @@ -6533,9 +6554,7 @@ __mmplayer_deactivate_old_path(mmplayer_t *player) player->streamer = NULL; } - MMPLAYER_PLAYBACK_LOCK(player); MMPLAYER_GAPLESS_PLAY_THREAD_SIGNAL(player); - MMPLAYER_FLEAVE(); return; @@ -7312,15 +7331,14 @@ __mmplayer_gst_decode_drained(GstElement *bin, gpointer data) return; } - if (!player->gapless.reconfigure && /* If it is already checked, skip verify. */ - !__mmplayer_verify_gapless_play_path(player)) { + if (!__mmplayer_verify_gapless_play_path(player)) { LOGD("decoding is finished."); - __mmplayer_reset_gapless_state(player); MMPLAYER_CMD_UNLOCK(player); return; } - player->gapless.reconfigure = TRUE; + _mmplayer_set_reconfigure_state(player, TRUE); + MMPLAYER_CMD_UNLOCK(player); /* check decodebin src pads whether they received EOS or not */ iter = gst_element_iterate_src_pads(player->pipeline->mainbin[MMPLAYER_M_AUTOPLUG].gst); @@ -7350,7 +7368,6 @@ __mmplayer_gst_decode_drained(GstElement *bin, gpointer data) if (!is_all_drained) { LOGD("Wait util the all pads get EOS."); - MMPLAYER_CMD_UNLOCK(player); MMPLAYER_FLEAVE(); return; } @@ -7361,7 +7378,6 @@ __mmplayer_gst_decode_drained(GstElement *bin, gpointer data) /* deactivate pipeline except sinkbins to set up the new pipeline of next uri*/ MMPLAYER_POST_MSG(player, MM_MESSAGE_GAPLESS_CONSTRUCTION, NULL); /* post message for gapless */ __mmplayer_deactivate_old_path(player); - MMPLAYER_CMD_UNLOCK(player); MMPLAYER_FLEAVE(); } @@ -7567,9 +7583,8 @@ __mmplayer_release_misc_post(mmplayer_t *player) } /* clean the uri list except original uri */ - if (player->uri_info.uri_list) { + if (player->uri_info.uri_list && g_list_length(player->uri_info.uri_list) > 1) { original_uri = g_list_nth_data(player->uri_info.uri_list, 0); - if (!original_uri) LOGW("failed to get original uri info"); @@ -7579,10 +7594,9 @@ __mmplayer_release_misc_post(mmplayer_t *player) GList *uri_list = player->uri_info.uri_list; for (; uri_list; uri_list = g_list_next(uri_list)) { gchar *uri = uri_list->data; - MMPLAYER_FREEIF(uri); + if (original_uri != uri) + MMPLAYER_FREEIF(uri); } - g_list_free(player->uri_info.uri_list); - player->uri_info.uri_list = NULL; } /* clear the audio stream buffer list */ diff --git a/unittest/gtest_mm_player_priv.cpp b/unittest/gtest_mm_player_priv.cpp index cfd830b..b5f6c05 100644 --- a/unittest/gtest_mm_player_priv.cpp +++ b/unittest/gtest_mm_player_priv.cpp @@ -27,7 +27,8 @@ MMPlayerPriv::~MMPlayerPriv() if (priv_player) { _mmplayer_destroy((MMHandleType)priv_player); g_mutex_clear(&priv_player->cmd_lock); - g_mutex_clear(&priv_player->playback_lock); + g_mutex_clear(&priv_player->reconfigure_lock); + g_cond_clear(&priv_player->reconfigure_cond); g_free(priv_player); priv_player = NULL; @@ -45,8 +46,9 @@ int MMPlayerPriv::Create(void) /* create player lock */ g_mutex_init(&new_player->cmd_lock); - /* create player lock */ - g_mutex_init(&new_player->playback_lock); + /* create reconfigure lock & cond */ + g_mutex_init(&new_player->reconfigure_lock); + g_cond_init(&new_player->recongifure_cond); /* load ini files */ if (mm_player_ini_load(&new_player->ini) != MM_ERROR_NONE) { @@ -83,7 +85,8 @@ int MMPlayerPriv::Destroy(void) MMPLAYER_CMD_UNLOCK(priv_player); g_mutex_clear(&((mmplayer_t *)priv_player)->cmd_lock); - g_mutex_clear(&((mmplayer_t *)priv_player)->playback_lock); + g_mutex_clear(&((mmplayer_t *)priv_player)->reconfigure_lock); + g_cond_clear(&((mmplayer_t *)priv_player)->reconfigure_cond); memset((mmplayer_t *)priv_player, 0x00, sizeof(mmplayer_t)); -- 2.7.4