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);
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:
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");
}
} 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 */
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;
attrs = MMPLAYER_GET_ATTRS(player);
if (!attrs) {
LOGE("cannot get content attribute");
- ret = FALSE;
break;
}
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");
}
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
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;
__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) {
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);
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);
/* 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;
}
__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);
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);
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) {
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;
}
result = __mmplayer_change_external_subtitle_language(player, filepath);
}
+ MMPLAYER_BUS_MSG_THREAD_SIGNAL(player);
player->is_external_subtitle_added_now = TRUE;
}