[0.6.64] handle the gst msg in seperate thread 21/162421/2 accepted/tizen/3.0/common/20171204.105112 accepted/tizen/3.0/mobile/20171204.064501 accepted/tizen/3.0/tv/20171204.064506 accepted/tizen/3.0/wearable/20171204.064510 submit/tizen_3.0/20171201.071736
authorEunhae Choi <eunhae1.choi@samsung.com>
Fri, 1 Dec 2017 03:07:04 +0000 (12:07 +0900)
committerEunhae Choi <eunhae1.choi@samsung.com>
Fri, 1 Dec 2017 07:02:46 +0000 (16:02 +0900)
- remove bus watch not to use main loop
- add new thread for handling the bus msg

Change-Id: I83988effec1cf97e1e1f272a28bc0fa9d6529370

packaging/libmm-player.spec
src/include/mm_player_priv.h
src/include/mm_player_utils.h
src/mm_player.c
src/mm_player_priv.c

index eaa2844327718c59452fc870b2b60917f0e6b73c..45b014868a60b2d8f3d6baf581c6aeb5d3038571 100644 (file)
@@ -1,6 +1,6 @@
 Name:       libmm-player
 Summary:    Multimedia Framework Player Library
-Version:    0.6.63
+Version:    0.6.64
 Release:    0
 Group:      Multimedia/Libraries
 License:    Apache-2.0
index 54bec62cfa1454c9cc42f226e1bccee93ec4e52f..7df737f676714f94f62499ad979865f014a3b004 100644 (file)
@@ -399,11 +399,6 @@ typedef struct {
        bool media_packet_video_stream;
 } MMPlayerSetMode;
 
-typedef struct {
-       GMainContext *global_default;
-       GMainContext *thread_default;
-} MMPlayerGMainContext;
-
 typedef struct {
        gint uri_idx;
        GList *uri_list;
@@ -493,6 +488,12 @@ typedef struct {
        MMPlayerVideoColorspace video_cs;
        MMVideoBuffer captured;
 
+       /* gst bus msg thread, create during realize */
+       GThread* bus_msg_thread;
+       gboolean bus_msg_thread_exit;
+       GCond bus_msg_thread_cond;
+       GMutex bus_msg_thread_mutex;
+
        /* fakesink handling lock */
        GMutex fsink_lock;
 
@@ -652,8 +653,7 @@ typedef struct {
 
        /* signal notifiers */
        GList* signals[MM_PLAYER_SIGNAL_TYPE_MAX];
-       guint bus_watcher;
-       MMPlayerGMainContext context;
+       GMainContext *global_default;
        MMPlayerUriList uri_info;
 
        gboolean is_sound_extraction;
@@ -864,6 +864,8 @@ int __mmplayer_set_state(mm_player_t* player, int state);
 int __mmplayer_check_state(mm_player_t* player, enum PlayerCommandState command);
 gboolean __mmplayer_dump_pipeline_state(mm_player_t* player);
 void __mmplayer_remove_g_source_from_context(GMainContext *context, guint source_id);
+void _mmplayer_bus_msg_thread_destroy(MMHandleType hplayer);
+
 /* util */
 const gchar * __get_state_name(int state);
 gboolean __mmplayer_can_do_interrupt(mm_player_t *player);
index cf4d2ac44f1f35522fd3b129bd510edffa73d76f..9f003842526f319f2fa9523e7effc44fa32a2c44 100644 (file)
@@ -84,6 +84,13 @@ do { \
 #define MMPLAYER_REPEAT_THREAD_WAIT(x_player)                g_cond_wait(&((mm_player_t *)x_player)->repeat_thread_cond, &((mm_player_t *)x_player)->repeat_thread_mutex)
 #define MMPLAYER_REPEAT_THREAD_SIGNAL(x_player)              g_cond_signal(&((mm_player_t *)x_player)->repeat_thread_cond);
 
+/* gst bus msg thread */
+#define MMPLAYER_BUS_MSG_THREAD_LOCK(x_player)                   g_mutex_lock(&((mm_player_t *)x_player)->bus_msg_thread_mutex)
+#define MMPLAYER_BUS_MSG_THREAD_UNLOCK(x_player)                 g_mutex_unlock(&((mm_player_t *)x_player)->bus_msg_thread_mutex)
+#define MMPLAYER_BUS_MSG_THREAD_WAIT(x_player)                   g_cond_wait(&((mm_player_t *)x_player)->bus_msg_thread_cond, &((mm_player_t *)x_player)->bus_msg_thread_mutex)
+#define MMPLAYER_BUS_MSG_THREAD_WAIT_UNTIL(x_player, end_time)   g_cond_wait_until(&((mm_player_t *)x_player)->bus_msg_thread_cond, &((mm_player_t *)x_player)->bus_msg_thread_mutex, end_time)
+#define MMPLAYER_BUS_MSG_THREAD_SIGNAL(x_player)                 g_cond_signal(&((mm_player_t *)x_player)->bus_msg_thread_cond);
+
 /* handling fakesink */
 #define MMPLAYER_FSINK_LOCK(x_player)                        g_mutex_lock(&((mm_player_t *)x_player)->fsink_lock)
 #define MMPLAYER_FSINK_UNLOCK(x_player)                      g_mutex_unlock(&((mm_player_t *)x_player)->fsink_lock)
index b420446b4f6453ee318c15649b8fb06d430e90f7..f5e9c0895d4e307fa35b9026efa3f4ec6dece32a 100644 (file)
@@ -108,24 +108,23 @@ int  mm_player_destroy(MMHandleType player)
 
        MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
 
-       MMPLAYER_CMD_LOCK( player );
+       /* destroy the gst bus msg thread if it is remained.
+          this funct have to be called before getting cmd lock. */
+       _mmplayer_bus_msg_thread_destroy(player);
+
+       MMPLAYER_CMD_LOCK(player);
 
        result = _mmplayer_destroy(player);
 
        MMPLAYER_CMD_UNLOCK(player);
 
-       /* to make sure unlocked.
-          @see __mmplayer_gst_callback, GST_MESSAGE_BUFFERING handling */
-       MMPLAYER_CMD_LOCK(player);
-       MMPLAYER_CMD_UNLOCK( player );
-
        g_mutex_clear(&((mm_player_t*)player)->cmd_lock);
        g_mutex_clear(&((mm_player_t*)player)->playback_lock);
 
-       memset( (mm_player_t*)player, 0x00, sizeof(mm_player_t) );
+       memset((mm_player_t*)player, 0x00, sizeof(mm_player_t));
 
        /* free player */
-       g_free( (void*)player );
+       g_free((void*)player);
 
        return result;
 }
@@ -182,7 +181,7 @@ int mm_player_unrealize(MMHandleType player)
 
        MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
 
-       MMPLAYER_CMD_LOCK( player );
+       MMPLAYER_CMD_LOCK(player);
 
        result = _mmplayer_unrealize(player);
 
index fc521748106c7bd36f114608a7a4754b811162c2..c2e6732a4731243f1ca748880cbc2e54a34fbb2a 100644 (file)
@@ -174,7 +174,7 @@ static void         __mmplayer_release_misc(mm_player_t* player);
 static void            __mmplayer_release_misc_post(mm_player_t* player);
 static gboolean        __mmplayer_init_gstreamer(mm_player_t* player);
 static GstBusSyncReply __mmplayer_bus_sync_callback(GstBus * bus, GstMessage * message, gpointer data);
-static gboolean __mmplayer_gst_callback(GstBus *bus, GstMessage *msg, gpointer data);
+static void __mmplayer_gst_callback(GstMessage *msg, gpointer data);
 
 static gboolean        __mmplayer_gst_extract_tag_from_msg(mm_player_t* player, GstMessage *msg);
 static gboolean      __mmplayer_gst_handle_duration(mm_player_t* player, GstMessage* msg);
@@ -1104,15 +1104,83 @@ __mmplayer_drop_subtitle(mm_player_t* player, gboolean is_drop)
        }
 }
 
-static gboolean
-__mmplayer_gst_callback(GstBus *bus, GstMessage *msg, gpointer data) // @
+void _mmplayer_bus_msg_thread_destroy(MMHandleType hplayer)
 {
-       mm_player_t* player = (mm_player_t*) data;
-       gboolean ret = TRUE;
+       mm_player_t* player = (mm_player_t*)hplayer;
+
+       MMPLAYER_FENTER();
+       MMPLAYER_RETURN_IF_FAIL(player);
+
+       /* destroy the gst bus msg thread */
+       if (player->bus_msg_thread) {
+               MMPLAYER_BUS_MSG_THREAD_LOCK(player);
+               player->bus_msg_thread_exit = TRUE;
+               MMPLAYER_BUS_MSG_THREAD_SIGNAL(player);
+               MMPLAYER_BUS_MSG_THREAD_UNLOCK(player);
+
+               LOGD("gst bus msg thread exit.");
+               g_thread_join(player->bus_msg_thread);
+               player->bus_msg_thread = NULL;
+
+               g_mutex_clear(&player->bus_msg_thread_mutex);
+               g_cond_clear(&player->bus_msg_thread_cond);
+       }
+
+       MMPLAYER_FLEAVE();
+}
+
+static gpointer __mmplayer_gst_bus_msg_thread(gpointer data)
+{
+       mm_player_t *player = (mm_player_t*)(data);
+       GstMessage *msg = NULL;
+       GstBus *bus = NULL;
+
+       MMPLAYER_FENTER();
+       MMPLAYER_RETURN_VAL_IF_FAIL(player &&
+                                               player->pipeline &&
+                                               player->pipeline->mainbin &&
+                                               player->pipeline->mainbin[MMPLAYER_M_PIPE].gst,
+                                               NULL);
+
+       bus = gst_pipeline_get_bus(GST_PIPELINE(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst));
+       if (!bus) {
+               LOGE("cannot get BUS from the pipeline");
+               return NULL;
+       }
+
+       MMPLAYER_BUS_MSG_THREAD_LOCK(player);
+
+       LOGD("gst bus msg thread will be started.");
+       while (!player->bus_msg_thread_exit) {
+               msg = gst_bus_pop(bus);
+               if (msg == NULL) {
+                       /* set the max timeout as 500 ms */
+                       MMPLAYER_BUS_MSG_THREAD_WAIT_UNTIL(player, (g_get_monotonic_time() + 500 * G_TIME_SPAN_MILLISECOND));
+                       continue;
+               }
+
+               MMPLAYER_BUS_MSG_THREAD_UNLOCK(player);
+               /* handle the gst msg */
+               __mmplayer_gst_callback(msg, player);
+               MMPLAYER_BUS_MSG_THREAD_LOCK(player);
+               gst_message_unref(msg);
+       }
+
+       MMPLAYER_BUS_MSG_THREAD_UNLOCK(player);
+       gst_object_unref(GST_OBJECT(bus));
+
+       MMPLAYER_FLEAVE();
+       return NULL;
+}
+
+static void
+__mmplayer_gst_callback(GstMessage *msg, gpointer data)
+{
+       mm_player_t* player = (mm_player_t*)(data);
        static gboolean async_done = FALSE;
 
-       MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
-       MMPLAYER_RETURN_VAL_IF_FAIL(msg && GST_IS_MESSAGE(msg), FALSE);
+       MMPLAYER_RETURN_IF_FAIL(player);
+       MMPLAYER_RETURN_IF_FAIL(msg && GST_IS_MESSAGE(msg));
 
        switch (GST_MESSAGE_TYPE(msg)) {
        case GST_MESSAGE_UNKNOWN:
@@ -1305,11 +1373,6 @@ __mmplayer_gst_callback(GstBus *bus, GstMessage *msg, gpointer data) // @
                                }
                        } else {
                                MMPLAYER_CMD_LOCK(player);
-                               if (!player->pipeline) { /* during destroy, msg can be delivered. */
-                                       LOGE("pipeline is destroyed.");
-                                       MMPLAYER_CMD_UNLOCK(player);
-                                       break;
-                               }
                        }
 
                        /* ignore the prev buffering message */
@@ -1556,7 +1619,6 @@ __mmplayer_gst_callback(GstBus *bus, GstMessage *msg, gpointer data) // @
                                attrs = MMPLAYER_GET_ATTRS(player);
                                if (!attrs) {
                                        LOGE("cannot get content attribute");
-                                       ret = FALSE;
                                        break;
                                }
 
@@ -1677,8 +1739,7 @@ __mmplayer_gst_callback(GstBus *bus, GstMessage *msg, gpointer data) // @
        case GST_MESSAGE_DURATION_CHANGED:
                {
                        LOGD("GST_MESSAGE_DURATION_CHANGED\n");
-                       ret = __mmplayer_gst_handle_duration(player, msg);
-                       if (!ret)
+                       if (!__mmplayer_gst_handle_duration(player, msg))
                                LOGW("failed to update duration");
                }
 
@@ -1753,12 +1814,8 @@ __mmplayer_gst_callback(GstBus *bus, GstMessage *msg, gpointer data) // @
                break;
        }
 
-       /* FIXIT : this cause so many warnings/errors from glib/gstreamer. we should not call it since
-        * gst_element_post_message api takes ownership of the message.
-        */
-       //gst_message_unref(msg);
-
-       return ret;
+       /* should not call 'gst_message_unref(msg)' */
+       return;
 }
 
 static gboolean
@@ -5991,7 +6048,7 @@ __mmplayer_bus_sync_callback(GstBus * bus, GstMessage * message, gpointer data)
        case GST_MESSAGE_STATE_CHANGED:
                /* post directly for fast launch */
                if (player->sync_handler) {
-                       __mmplayer_gst_callback(NULL, message, player);
+                       __mmplayer_gst_callback(message, player);
                        reply = GST_BUS_DROP;
                } else
                        reply = GST_BUS_PASS;
@@ -6751,6 +6808,12 @@ __mmplayer_gst_create_pipeline(mm_player_t* player) // @
                        __mmplayer_try_to_plug_decodebin(player, gst_element_get_static_pad(mainbin[MMPLAYER_M_S_BUFFER].gst, "src"), player->s_stream_caps);
        }
 
+       /* Note : check whether subtitle atrribute uri is set. If uri is set, then try to play subtitle file */
+       if (__mmplayer_check_subtitle(player)) {
+               if (MM_ERROR_NONE != __mmplayer_gst_create_subtitle_src(player))
+                       LOGE("fail to create text pipeline");
+       }
+
        /* connect bus callback */
        bus = gst_pipeline_get_bus(GST_PIPELINE(mainbin[MMPLAYER_M_PIPE].gst));
        if (!bus) {
@@ -6758,22 +6821,6 @@ __mmplayer_gst_create_pipeline(mm_player_t* player) // @
                goto INIT_ERROR;
        }
 
-       player->bus_watcher = gst_bus_add_watch(bus, (GstBusFunc)__mmplayer_gst_callback, player);
-
-       player->context.thread_default = g_main_context_get_thread_default();
-
-       if (NULL == player->context.thread_default) {
-               player->context.thread_default = g_main_context_default();
-               LOGD("thread-default context is the global default context");
-       }
-       LOGW("bus watcher thread context = %p, watcher : %d", player->context.thread_default, player->bus_watcher);
-
-       /* Note : check whether subtitle atrribute uri is set. If uri is set, then try to play subtitle file */
-       if (__mmplayer_check_subtitle(player)) {
-               if (MM_ERROR_NONE != __mmplayer_gst_create_subtitle_src(player))
-                       LOGE("fail to create subtitle src\n");
-       }
-
        /* set sync handler to get tag synchronously */
        gst_bus_set_sync_handler(bus, __mmplayer_bus_sync_callback, player, NULL);
 
@@ -6781,6 +6828,19 @@ __mmplayer_gst_create_pipeline(mm_player_t* player) // @
        gst_object_unref(GST_OBJECT(bus));
        g_list_free(element_bucket);
 
+       /* create gst bus_msb_cb thread */
+       g_mutex_init(&player->bus_msg_thread_mutex);
+       g_cond_init(&player->bus_msg_thread_cond);
+       player->bus_msg_thread_exit = FALSE;
+       player->bus_msg_thread =
+               g_thread_try_new("gst_bus_msg_thread", __mmplayer_gst_bus_msg_thread, (gpointer)player, NULL);
+       if (!player->bus_msg_thread) {
+               LOGE("failed to create gst BUS msg thread");
+               g_mutex_clear(&player->bus_msg_thread_mutex);
+               g_cond_clear(&player->bus_msg_thread_cond);
+               goto INIT_ERROR;
+       }
+
        MMPLAYER_FLEAVE();
 
        return MM_ERROR_NONE;
@@ -6878,11 +6938,6 @@ __mmplayer_gst_destroy_pipeline(mm_player_t* player) // @
                /* first we need to disconnect all signal hander */
                __mmplayer_release_signal_connection(player, MM_PLAYER_SIGNAL_TYPE_ALL);
 
-               /* disconnecting bus watch */
-               if (player->bus_watcher)
-                       __mmplayer_remove_g_source_from_context(player->context.thread_default, player->bus_watcher);
-               player->bus_watcher = 0;
-
                if (mainbin) {
                        MMPlayerGstElement* audiobin = player->pipeline->audiobin;
                        MMPlayerGstElement* videobin = player->pipeline->videobin;
@@ -8221,9 +8276,10 @@ void __mmplayer_sound_focus_watch_callback(int id, mm_sound_focus_type_e focus_t
                                }
 
                                __mmplayer_undo_sound_fadedown(player);
-                       } else
+                       } else {
                                /* rtsp should connect again in specific network becasue tcp session can't be kept any more */
                                _mmplayer_unrealize((MMHandleType)player);
+                       }
                } else {
                        LOGW("pause immediately");
                        result = _mmplayer_pause((MMHandleType)player);
@@ -9014,7 +9070,13 @@ _mmplayer_unrealize(MMHandleType hplayer)
 
        MMPLAYER_FENTER();
 
-       MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED)
+       MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
+
+       MMPLAYER_CMD_UNLOCK(player);
+       /* destroy the gst bus msg thread which is created during realize.
+          this funct have to be called before getting cmd lock. */
+       _mmplayer_bus_msg_thread_destroy(player);
+       MMPLAYER_CMD_LOCK(player);
 
        /* check current state */
        MMPLAYER_CHECK_STATE(player, MMPLAYER_COMMAND_UNREALIZE);
@@ -13250,8 +13312,8 @@ __mmplayer_handle_eos_delay(mm_player_t* player, int delay_in_ms)
        player->eos_timer = g_timeout_add(delay_in_ms,
                __mmplayer_eos_timer_cb, player);
 
-       player->context.global_default = g_main_context_default();
-       LOGD("global default context = %p, eos timer id = %d", player->context.global_default, player->eos_timer);
+       player->global_default = g_main_context_default();
+       LOGD("global default context = %p, eos timer id = %d", player->global_default, player->eos_timer);
 
        /* check timer is valid. if not, send EOS now */
        if (player->eos_timer == 0) {
@@ -13267,7 +13329,7 @@ __mmplayer_cancel_eos_timer(mm_player_t* player)
 
        if (player->eos_timer) {
                LOGD("cancel eos timer");
-               __mmplayer_remove_g_source_from_context(player->context.global_default, player->eos_timer);
+               __mmplayer_remove_g_source_from_context(player->global_default, player->eos_timer);
                player->eos_timer = 0;
        }
 
@@ -14255,9 +14317,11 @@ int _mmplayer_set_external_subtitle_path(MMHandleType hplayer, const char* filep
                                LOGE("fail to create subtitle src\n");
 
                        result = _mmplayer_sync_subtitle_pipeline(player);
-               } else
+               } else {
                        result = __mmplayer_change_external_subtitle_language(player, filepath);
+               }
 
+               MMPLAYER_BUS_MSG_THREAD_SIGNAL(player);
                player->is_external_subtitle_added_now = TRUE;
        }