[0.6.207] use reconfigure lock to sync operation 90/215690/4 accepted/tizen/unified/20191101.042042 submit/tizen/20191021.065130
authorEunhye Choi <eunhae1.choi@samsung.com>
Mon, 14 Oct 2019 08:21:50 +0000 (17:21 +0900)
committerEunhye Choi <eunhae1.choi@samsung.com>
Mon, 21 Oct 2019 06:02:10 +0000 (15:02 +0900)
- 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
src/include/mm_player_priv.h
src/include/mm_player_utils.h
src/mm_player.c
src/mm_player_gst.c
src/mm_player_priv.c
unittest/gtest_mm_player_priv.cpp

index b8eed46..67e6699 100644 (file)
@@ -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
index 5431dfd..25c944c 100644 (file)
@@ -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
        }
index b0f9630..4f12889 100644 (file)
 #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)
index 4134c2f..bcd2d7d 100644 (file)
@@ -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
+}
index edd913d..25b1cd9 100644 (file)
@@ -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;
index 6f1a7d6..1c585c3 100644 (file)
@@ -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 */
index cfd830b..b5f6c05 100644 (file)
@@ -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));