[v0.3.46] remove the idle ev if the cb is unset 64/112864/1 accepted/tizen/common/20170206.124355 submit/tizen/20170206.043356
authorEunhae Choi <eunhae1.choi@samsung.com>
Fri, 3 Feb 2017 03:01:06 +0000 (12:01 +0900)
committerEunhae Choi <eunhae1.choi@samsung.com>
Fri, 3 Feb 2017 06:24:57 +0000 (15:24 +0900)
Change-Id: I13a21f5f637401fa95ecc405c408ef816def4ff6

packaging/capi-media-player.spec
src/player.c

index 18b2db7..14f8ac9 100644 (file)
@@ -1,6 +1,6 @@
 Name:       capi-media-player
 Summary:    A Media Player API
-Version:    0.3.45
+Version:    0.3.46
 Release:    0
 Group:      Multimedia/API
 License:    Apache-2.0
index 386dfff..127cdf4 100755 (executable)
@@ -78,12 +78,15 @@ typedef struct {
 */
 static int _player_deinit_memory_buffer(player_cli_s * pc);
 static void _player_event_queue_add(player_event_queue * ev, _player_cb_data * data);
+static bool _player_need_sync_context(int event_id);
+static void _player_remove_idle_event(callback_cb_info_s *cb_info, muse_player_event_e event_type, bool remove_all);
 #ifdef TIZEN_FEATURE_EVAS_RENDERER
 typedef void (*player_retrieve_buffer_cb)(void *user_data);
 static void __retrieve_buffer_cb(void *user_data);
 static int __player_set_retrieve_buffer_cb(player_h player, player_retrieve_buffer_cb callback, void *user_data);
 static int __player_unset_retrieve_buffer_cb(player_h player);
 #endif
+
 int _player_media_packet_finalize(media_packet_h pkt, int error_code, void *user_data)
 {
        int ret = MEDIA_PACKET_FINALIZE;
@@ -431,6 +434,9 @@ static void set_null_user_cb(callback_cb_info_s * cb_info, muse_player_event_e e
        }
 }
 
+/* Notice : have to be called via API to avoid deadlock
+ * to clear the cb setting at the cb thread, set_null_user_cb() have to be called instead.
+ */
 static void set_null_user_cb_lock(callback_cb_info_s * cb_info, muse_player_event_e event)
 {
        bool lock = g_thread_self() != cb_info->event_queue.thread;
@@ -438,7 +444,10 @@ static void set_null_user_cb_lock(callback_cb_info_s * cb_info, muse_player_even
        if (lock)
                g_mutex_lock(&cb_info->event_queue.mutex);
 
-       set_null_user_cb(cb_info, event);
+       if (_player_need_sync_context(event))
+               _player_remove_idle_event(cb_info, event, false);
+       else
+               set_null_user_cb(cb_info, event);
 
        if (lock)
                g_mutex_unlock(&cb_info->event_queue.mutex);
@@ -1126,6 +1135,7 @@ static void (*_user_callbacks[MUSE_PLAYER_EVENT_TYPE_NUM]) (callback_cb_info_s *
 gboolean _player_event_job_function(void *user_data)
 {
        _player_cb_data *data = (_player_cb_data *)user_data;
+       muse_player_event_e ev;
 
        if (data == NULL) {
                LOGE("data is null");
@@ -1135,8 +1145,13 @@ gboolean _player_event_job_function(void *user_data)
        /* LOGD("enter ev:%d", data->int_data); */
 
        g_mutex_lock(&data->event_mutex);
+       ev = data->int_data;
 
-       muse_player_event_e ev = data->int_data;
+       if (data->cb_info == NULL) {
+               /* tried to remove before at _player_remove_idle_event */
+               LOGW("cb_info is NULL. event %d", data->int_data);
+               goto DONE;
+       }
 
        /* remove event from list */
        g_mutex_lock(&data->cb_info->event_queue.idle_ev_mutex);
@@ -1151,6 +1166,7 @@ gboolean _player_event_job_function(void *user_data)
        else
                LOGW("user callback is unset. type : %d", ev);
 
+DONE:
        /* unlock and release event */
        g_mutex_unlock(&data->event_mutex);
        g_mutex_clear(&data->event_mutex);
@@ -1263,7 +1279,7 @@ static gboolean _player_event_queue_new(callback_cb_info_s * cb_info)
 
 }
 
-static void _player_remove_idle_event_all(callback_cb_info_s *cb_info)
+static void _player_remove_idle_event(callback_cb_info_s *cb_info, muse_player_event_e event_type, bool remove_all)
 {
        g_return_if_fail(cb_info);
        player_event_queue *ev = &cb_info->event_queue;
@@ -1277,6 +1293,8 @@ static void _player_remove_idle_event_all(callback_cb_info_s *cb_info)
                GList *list = NULL;
                list = ev->idle_ev_list;
 
+               LOGD("remove idle event [%d] or all[%d]", event_type, remove_all);
+
                while (list) {
                        event_data = list->data;
 
@@ -1288,26 +1306,39 @@ static void _player_remove_idle_event_all(callback_cb_info_s *cb_info)
                                        bool ret = FALSE;
 
                                        list = g_list_next(list);
-                                       ret = g_idle_remove_by_data(event_data);
 
-                                       LOGD("remove idle event [%p], ret[%d]", event_data, ret);
+                                       if (remove_all || (event_data->int_data == event_type)) {
 
-                                       if (ret == FALSE) {
-                                               event_data->cb_info = NULL;
-                                               LOGW("idle callback for event %p will be called later", event_data);
-                                       }
+                                               LOGD("remove idle event [%p:%d]", event_data, event_data->int_data);
 
-                                       ev->idle_ev_list = g_list_remove(ev->idle_ev_list, (gpointer)event_data);
+                                               ret = g_idle_remove_by_data(event_data);
+                                               if (ret == FALSE) {
+                                                       /* will be handled at _player_event_job_function() as an exception */
+                                                       event_data->cb_info = NULL;
+                                                       LOGW("failed to remove, idle callback will be called later");
+                                               } else {
+                                                       /* set cb to null */
+                                                       set_null_user_cb(cb_info, event_data->int_data);
+                                               }
+
+                                               ev->idle_ev_list = g_list_remove(ev->idle_ev_list, (gpointer)event_data);
 
-                                       g_mutex_unlock(&event_data->event_mutex);
+                                               g_mutex_unlock(&event_data->event_mutex);
 
-                                       if (ret == TRUE) {
-                                               g_mutex_clear(&event_data->event_mutex);
+                                               if (ret == TRUE) {
+                                                       g_mutex_clear(&event_data->event_mutex);
 
-                                               g_free(event_data);
-                                               event_data = NULL;
+                                                       g_free(event_data);
+                                                       event_data = NULL;
 
-                                               LOGD("remove idle event done");
+                                                       LOGD("remove idle event done");
+                                               } /* else : will be handled if the cb is called. */
+
+                                               if (!remove_all) {
+                                                       LOGD("remove idle [%d] event", event_type);
+                                                       g_mutex_unlock(&ev->idle_ev_mutex);
+                                                       return;
+                                               }
                                        }
                                } else {
                                        LOGW("event(%d) lock failed. it's being called...", event_data->int_data);
@@ -1842,7 +1873,7 @@ int player_destroy(player_h player)
 
        if (CALLBACK_INFO(pc)) {
                __player_remove_tsurf_list(pc);
-               _player_remove_idle_event_all(CALLBACK_INFO(pc));
+               _player_remove_idle_event(CALLBACK_INFO(pc), MUSE_PLAYER_EVENT_TYPE_NUM, true);
                _player_event_queue_destroy(CALLBACK_INFO(pc));
                tbm_bufmgr_deinit(TBM_BUFMGR(pc));