From: Eunhae Choi Date: Thu, 30 Nov 2017 13:52:33 +0000 (+0900) Subject: [0.6.82] handle the gst msg in seperate thread X-Git-Tag: submit/tizen_4.0/20171201.065254^0 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=53dee29e410a83198be5502b1e39ff8cea4d58bd;p=platform%2Fcore%2Fmultimedia%2Flibmm-player.git [0.6.82] handle the gst msg in seperate thread - remove bus watch - add new thread for handling bus msg Change-Id: Idaf161fe8fe442a8b8f001ec93ca654fb9ba3f10 --- diff --git a/packaging/libmm-player.spec b/packaging/libmm-player.spec index 0d8cc64..b101953 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.81 +Version: 0.6.82 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 78fd9f6..dbec7f9 100644 --- a/src/include/mm_player_priv.h +++ b/src/include/mm_player_priv.h @@ -401,11 +401,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; @@ -506,6 +501,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; @@ -665,8 +666,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; @@ -865,6 +865,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); diff --git a/src/include/mm_player_utils.h b/src/include/mm_player_utils.h index 6890e58..0ff257a 100644 --- a/src/include/mm_player_utils.h +++ b/src/include/mm_player_utils.h @@ -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) diff --git a/src/mm_player.c b/src/mm_player.c index 5fce28b..13f8684 100644 --- a/src/mm_player.c +++ b/src/mm_player.c @@ -104,17 +104,16 @@ int mm_player_destroy(MMHandleType player) MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED); + /* 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); diff --git a/src/mm_player_priv.c b/src/mm_player_priv.c index 677c1b9..1d292b4 100644 --- a/src/mm_player_priv.c +++ b/src/mm_player_priv.c @@ -151,7 +151,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); static gboolean __mmplayer_gst_remove_fakesink(mm_player_t* player, MMPlayerGstElement* fakesink); @@ -1081,15 +1081,83 @@ __mmplayer_adaptive_var_info(const VariantData *self, gpointer user_data) return var_info; } -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); /* can request cmd lock */ + 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: @@ -1269,6 +1337,7 @@ __mmplayer_gst_callback(GstBus *bus, GstMessage *msg, gpointer data) if (player->pd_mode == MM_PLAYER_PD_MODE_URI) { if (!MMPLAYER_CMD_TRYLOCK(player)) { + /* skip the playback control by buffering msg while user request is handled. */ gint per = 0; LOGW("[PD mode] can't get cmd lock, only post buffering msg"); @@ -1282,11 +1351,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 */ @@ -1449,6 +1513,13 @@ __mmplayer_gst_callback(GstBus *bus, GstMessage *msg, gpointer data) if (MMPLAYER_IS_STREAMING(player) && (player->streamer)) __mm_player_streaming_set_content_bitrate(player->streamer, player->total_maximum_bitrate, player->total_bitrate); + + if (player->pending_seek.is_pending) { + LOGW("trying to do pending seek"); + MMPLAYER_CMD_LOCK(player); + __gst_pending_seek(player); + MMPLAYER_CMD_UNLOCK(player); + } } } break; @@ -1533,7 +1604,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; } @@ -1683,8 +1753,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"); } @@ -1759,12 +1828,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 @@ -5932,7 +5997,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; @@ -6690,6 +6755,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_text_pipeline(player)) + LOGE("fail to create text pipeline"); + } + /* connect bus callback */ bus = gst_pipeline_get_bus(GST_PIPELINE(mainbin[MMPLAYER_M_PIPE].gst)); if (!bus) { @@ -6697,22 +6768,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_text_pipeline(player)) - LOGE("fail to create text pipeline"); - } - /* set sync handler to get tag synchronously */ gst_bus_set_sync_handler(bus, __mmplayer_bus_sync_callback, player, NULL); @@ -6720,12 +6775,24 @@ __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; INIT_ERROR: - __mmplayer_gst_destroy_pipeline(player); g_list_free(element_bucket); @@ -6817,11 +6884,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; @@ -8150,9 +8212,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); @@ -8935,7 +8998,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); @@ -12063,8 +12132,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) { @@ -12080,7 +12149,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; } @@ -12989,6 +13058,7 @@ int _mmplayer_set_external_subtitle_path(MMHandleType hplayer, const char* filep result = __mmplayer_change_external_subtitle_language(player, filepath); } + MMPLAYER_BUS_MSG_THREAD_SIGNAL(player); player->is_external_subtitle_added_now = TRUE; }