X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Fmm_player_priv.c;h=b1559a825ff528edd142eccbb61a1fcc78c876a9;hb=76ca5133e2ed75afcd9db521bdc71f319f9c215f;hp=d297f1e848873293a82953b204a8ccb838b0379d;hpb=02ca170dea3ce3e5ee00c655eeebb12b88a8dd88;p=platform%2Fcore%2Fmultimedia%2Flibmm-player.git diff --git a/src/mm_player_priv.c b/src/mm_player_priv.c index d297f1e..b1559a8 100644 --- a/src/mm_player_priv.c +++ b/src/mm_player_priv.c @@ -43,7 +43,6 @@ #include "mm_player_priv.h" #include "mm_player_ini.h" -#include "mm_player_attrs.h" #include "mm_player_capture.h" #include "mm_player_utils.h" #include "mm_player_tracks.h" @@ -179,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); @@ -691,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) { @@ -707,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; } @@ -750,6 +756,42 @@ __mmplayer_remove_g_source_from_context(GMainContext *context, guint source_id) } void +_mmplayer_watcher_removed_notify(gpointer data) +{ + mmplayer_t *player = (mmplayer_t *)data; + MMPLAYER_RETURN_IF_FAIL(player); + + MMPLAYER_BUS_WATCHER_LOCK(player); + player->bus_watcher = 0; + MMPLAYER_BUS_WATCHER_SIGNAL(player); + MMPLAYER_BUS_WATCHER_UNLOCK(player); +} + +void +_mmplayer_bus_watcher_remove(MMHandleType hplayer) +{ + mmplayer_t *player = (mmplayer_t *)hplayer; + gint64 end_time = 0; + MMPLAYER_FENTER(); + MMPLAYER_RETURN_IF_FAIL(player); + + /* disconnecting bus watch */ + if (player->bus_watcher > 0) { + __mmplayer_remove_g_source_from_context(player->context.thread_default, player->bus_watcher); + MMPLAYER_BUS_WATCHER_LOCK(player); + end_time = g_get_monotonic_time () + 2 * G_TIME_SPAN_SECOND; + while (player->bus_watcher > 0) + MMPLAYER_BUS_WATCHER_WAIT_UNTIL(player, end_time); + MMPLAYER_BUS_WATCHER_UNLOCK(player); + + g_mutex_clear(&player->bus_watcher_mutex); + g_cond_clear(&player->bus_watcher_cond); + } + + MMPLAYER_FLEAVE(); +} + +void _mmplayer_bus_msg_thread_destroy(MMHandleType hplayer) { mmplayer_t *player = (mmplayer_t *)hplayer; @@ -759,11 +801,6 @@ _mmplayer_bus_msg_thread_destroy(MMHandleType hplayer) MMPLAYER_FENTER(); MMPLAYER_RETURN_IF_FAIL(player); - /* disconnecting bus watch */ - if (player->bus_watcher) - __mmplayer_remove_g_source_from_context(player->context.thread_default, player->bus_watcher); - player->bus_watcher = 0; - /* destroy the gst bus msg thread */ if (player->bus_msg_thread) { MMPLAYER_BUS_MSG_THREAD_LOCK(player); @@ -1171,7 +1208,6 @@ _mmplayer_gst_decode_pad_added(GstElement *elem, GstPad *pad, gpointer data) const gchar *name = NULL; GstPad *sinkpad = NULL; gboolean first_track = FALSE; - gboolean caps_ret = TRUE; main_element_id_e elem_idx = MMPLAYER_M_NUM; mmplayer_track_type_e stream_type = MM_PLAYER_TRACK_TYPE_AUDIO; @@ -1183,8 +1219,13 @@ _mmplayer_gst_decode_pad_added(GstElement *elem, GstPad *pad, gpointer data) LOGD("pad-added signal handling"); /* get mimetype from caps */ - MMPLAYER_GST_GET_CAPS_INFO(pad, caps, str, name, caps_ret); - if (!caps_ret) + caps = gst_pad_get_current_caps(pad); + if (caps) { + str = gst_caps_get_structure(caps, 0); + if (str) + name = gst_structure_get_name(str); + } + if (!name) goto ERROR; MMPLAYER_LOG_GST_CAPS_TYPE(caps); @@ -1513,11 +1554,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(); } @@ -2539,13 +2576,16 @@ __mmplayer_gst_set_pulsesink_property(mmplayer_t *player) switch (latency_mode) { case AUDIO_LATENCY_MODE_LOW: - latency = g_strndup("low", 3); + latency = g_strdup("low"); break; case AUDIO_LATENCY_MODE_MID: - latency = g_strndup("mid", 3); + latency = g_strdup("mid"); break; case AUDIO_LATENCY_MODE_HIGH: - latency = g_strndup("high", 4); + latency = g_strdup("high"); + break; + default: + latency = g_strdup("mid"); break; }; @@ -2558,18 +2598,23 @@ __mmplayer_gst_set_pulsesink_property(mmplayer_t *player) MMPLAYER_FLEAVE(); } -void +int __mmplayer_gst_set_openalsink_property(mmplayer_t *player) { mmplayer_gst_element_t *audiobin = NULL; MMPLAYER_FENTER(); - MMPLAYER_RETURN_IF_FAIL(player && player->pipeline && player->pipeline->audiobin); + MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline && + player->pipeline->audiobin, MM_ERROR_PLAYER_NOT_INITIALIZED); audiobin = player->pipeline->audiobin; g_object_set(G_OBJECT(audiobin[MMPLAYER_A_SINK].gst), "source-ambisonics-type", 1, NULL); - sound_manager_create_stream_information(SOUND_STREAM_TYPE_MEDIA, NULL, NULL, &stream_info); + if (sound_manager_create_stream_information(SOUND_STREAM_TYPE_MEDIA, NULL, NULL, &stream_info)) { + LOGE("failed to create media stream info"); + return MM_ERROR_PLAYER_INTERNAL; + } + g_object_set(G_OBJECT(audiobin[MMPLAYER_A_SINK].gst), "stream-info", stream_info, NULL); if (player->video360_yaw_radians <= M_PI && @@ -2586,6 +2631,7 @@ __mmplayer_gst_set_openalsink_property(mmplayer_t *player) } MMPLAYER_FLEAVE(); + return MM_ERROR_NONE; } static int @@ -2723,10 +2769,12 @@ __mmplayer_gst_make_audio_playback_sink(mmplayer_t *player, GList **bucket) g_object_set(G_OBJECT(audiobin[MMPLAYER_A_SINK].gst), "provide-clock", FALSE, NULL); } - if (g_strrstr(player->ini.audiosink_element, "pulsesink")) + if (g_strrstr(player->ini.audiosink_element, "pulsesink")) { __mmplayer_gst_set_pulsesink_property(player); - else if (g_strrstr(player->ini.audiosink_element, "openalsink")) - __mmplayer_gst_set_openalsink_property(player); + } else if (g_strrstr(player->ini.audiosink_element, "openalsink")) { + if (__mmplayer_gst_set_openalsink_property(player) != MM_ERROR_NONE) + goto ERROR; + } /* qos on */ g_object_set(G_OBJECT(audiobin[MMPLAYER_A_SINK].gst), "qos", TRUE, NULL); /* qos on */ @@ -3453,19 +3501,18 @@ __mmplayer_gst_set_videosink_property(mmplayer_t *player, MMDisplaySurfaceType s return MM_ERROR_PLAYER_INTERNAL; } - LOGD("surface type %d, videosink factory name is %s", surface_type, factory_name); if (surface_type == MM_DISPLAY_SURFACE_OVERLAY) { bool use_tbm = (player->set_mode.video_zc || (player->is_360_feature_enabled && player->is_content_spherical)); - if (!use_tbm) { - /* support shard memory with S/W codec on HawkP */ - if (strncmp(factory_name, "tizenwlsink", strlen(factory_name)) == 0) { - g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst, - "use-tbm", use_tbm, NULL); - } + if (strncmp(factory_name, "tizenwlsink", strlen(factory_name)) == 0) { + g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst, + "use-tbm", use_tbm, NULL); } if (_mmplayer_update_video_overlay_param(player, "update_all_param") != MM_ERROR_NONE) return MM_ERROR_PLAYER_INTERNAL; + + LOGI("videosink factory name is %s use-tbm : %d", factory_name, use_tbm); + } else { g_object_set(G_OBJECT(player->pipeline->videobin[MMPLAYER_V_SINK].gst), "sync", TRUE, "max-lateness", FAKE_SINK_MAX_LATENESS, NULL); @@ -3784,7 +3831,7 @@ ERROR: if (textbin[MMPLAYER_T_BIN].gst) gst_object_unref(GST_OBJECT(textbin[MMPLAYER_T_BIN].gst)); - MMPLAYER_FREEIF(player->pipeline->textbin); + MMPLAYER_FREEIF(textbin); player->pipeline->textbin = NULL; MMPLAYER_FLEAVE(); @@ -4165,6 +4212,7 @@ __mmplayer_gst_create_pipeline(mmplayer_t *player) return MM_ERROR_NONE; INIT_ERROR: + _mmplayer_bus_watcher_remove(player); __mmplayer_gst_destroy_pipeline(player); return MM_ERROR_PLAYER_INTERNAL; } @@ -4204,7 +4252,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); @@ -4906,6 +4956,9 @@ _mmplayer_destroy(MMHandleType handle) player->resource_manager)) LOGE("failed to deinitialize resource manager"); + /* release miscellaneous information */ + __mmplayer_release_misc(player); + /* release pipeline */ if (MM_ERROR_NONE != __mmplayer_gst_destroy_pipeline(player)) { LOGE("failed to destory pipeline"); @@ -4920,9 +4973,6 @@ _mmplayer_destroy(MMHandleType handle) __mmplayer_release_dump_list(player->dump_list); - /* release miscellaneous information */ - __mmplayer_release_misc(player); - /* release miscellaneous information. these info needs to be released after pipeline is destroyed. */ __mmplayer_release_misc_post(player); @@ -4930,6 +4980,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); @@ -4949,11 +5009,13 @@ int _mmplayer_realize(MMHandleType hplayer) { mmplayer_t *player = (mmplayer_t *)hplayer; + int ret = MM_ERROR_NONE; char *uri = NULL; void *param = NULL; MMHandleType attrs = 0; - int ret = MM_ERROR_NONE; - + int video_codec_type = 0; + int audio_codec_type = 0; + int default_codec_type = 0; MMPLAYER_FENTER(); /* check player handle */ @@ -5037,6 +5099,23 @@ _mmplayer_realize(MMHandleType hplayer) player->streamer->buffering_req.rebuffer_time); } + mm_attrs_get_int_by_name(player->attrs, MM_PLAYER_AUDIO_CODEC_TYPE, &audio_codec_type); + if (!strcmp(player->ini.audiocodec_default_type, "hw")) + default_codec_type = MM_PLAYER_CODEC_TYPE_HW; + else + default_codec_type = MM_PLAYER_CODEC_TYPE_SW; + + if (audio_codec_type != default_codec_type) { + LOGD("audio dec sorting is required"); + player->need_audio_dec_sorting = TRUE; + } + + mm_attrs_get_int_by_name(player->attrs, MM_PLAYER_VIDEO_CODEC_TYPE, &video_codec_type); + if (video_codec_type != MM_PLAYER_CODEC_TYPE_DEFAULT) { + LOGD("video dec sorting is required"); + player->need_video_dec_sorting = TRUE; + } + /* realize pipeline */ ret = __mmplayer_gst_realize(player); if (ret != MM_ERROR_NONE) @@ -5060,6 +5139,7 @@ _mmplayer_unrealize(MMHandleType hplayer) MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED); MMPLAYER_CMD_UNLOCK(player); + _mmplayer_bus_watcher_remove(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); @@ -5412,28 +5492,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); - if (!player->gapless.reconfigure) - return; + MMPLAYER_RETURN_IF_FAIL(player && player->pipeline); - LOGW("pipeline is under construction."); + MMPLAYER_RECONFIGURE_LOCK(player); + if (!player->gapless.reconfigure) { + MMPLAYER_RECONFIGURE_UNLOCK(player); + return; + } - MMPLAYER_PLAYBACK_LOCK(player); - MMPLAYER_PLAYBACK_UNLOCK(player); + LOGI("reconfigure is under process"); + MMPLAYER_RECONFIGURE_WAIT(player); + MMPLAYER_RECONFIGURE_UNLOCK(player); + LOGI("reconfigure is completed."); - timeout = MMPLAYER_STATE_CHANGE_TIMEOUT(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); - /* 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*/ @@ -5450,9 +5534,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); @@ -5486,8 +5572,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: @@ -5694,8 +5780,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); @@ -5939,6 +6025,10 @@ _mmplayer_gst_make_decodebin(mmplayer_t *player) _mmplayer_add_signal_connection(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "autoplug-continue", G_CALLBACK(__mmplayer_gst_decode_autoplug_continue), (gpointer)player); + if (player->need_video_dec_sorting || player->need_audio_dec_sorting) + _mmplayer_add_signal_connection(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "autoplug-sort", + G_CALLBACK(_mmplayer_gst_decode_autoplug_sort), (gpointer)player); + /* This signal is emitted whenever decodebin finds a new stream. It is emitted before looking for any elements that can handle that stream.*/ _mmplayer_add_signal_connection(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "autoplug-select", @@ -6236,8 +6326,7 @@ __mmplayer_pipeline_complete(GstElement *decodebin, gpointer data) LOGD("[handle: %p] pipeline has completely constructed", player); - if ((player->ini.async_start) && - (player->msg_posted == FALSE) && + if ((player->msg_posted == FALSE) && (player->cmd >= MMPLAYER_COMMAND_START)) __mmplayer_handle_missed_plugin(player); @@ -6513,9 +6602,7 @@ __mmplayer_deactivate_old_path(mmplayer_t *player) player->streamer = NULL; } - MMPLAYER_PLAYBACK_LOCK(player); MMPLAYER_GAPLESS_PLAY_THREAD_SIGNAL(player); - MMPLAYER_FLEAVE(); return; @@ -6700,13 +6787,6 @@ __mmplayer_gst_decode_autoplug_continue(GstElement *bin, GstPad *pad, "content_audio_codec", "mobile-xmf", strlen("mobile-xmf"), NULL); MMPLAYER_FREEIF(caps_str); - } else if (g_str_has_prefix(mime, "video") && !player->ini.video_playback_supported) { - MMMessageParamType msg_param; - memset(&msg_param, 0, sizeof(MMMessageParamType)); - msg_param.code = MM_ERROR_NOT_SUPPORT_API; - MMPLAYER_POST_MSG(player, MM_MESSAGE_ERROR, &msg_param); - LOGD("video file is not supported on this device"); - ret = FALSE; } else if (g_str_has_prefix(mime, "video") && player->videodec_linked) { LOGD("already video linked"); ret = FALSE; @@ -6730,7 +6810,7 @@ __mmplayer_is_audio_offload_device_type(mmplayer_t *player) conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err); if (!conn || err) { - LOGE("failed g_bus_get_sync() (%s)", err ? err->message : NULL); + LOGE("failed g_bus_get_sync() (%s)", (err ? err->message : "null")); g_error_free(err); goto DONE; } @@ -6747,7 +6827,7 @@ __mmplayer_is_audio_offload_device_type(mmplayer_t *player) NULL, &err); if (!result || err) { - LOGE("failed g_dbus_connection_call_sync() (%s)", err ? err->message : NULL); + LOGE("failed g_dbus_connection_call_sync() (%s)", (err ? err->message : "null")); g_error_free(err); goto DONE; } @@ -6951,8 +7031,6 @@ static GstAutoplugSelectResult __mmplayer_check_codec_info(mmplayer_t *player, const char *klass, GstCaps *caps, char *factory_name) { GstAutoplugSelectResult ret = GST_AUTOPLUG_SELECT_TRY; - int idx = 0; - int codec_type = MM_PLAYER_CODEC_TYPE_DEFAULT; int audio_offload = 0; if ((g_strrstr(klass, "Codec/Decoder/Audio"))) { @@ -6970,27 +7048,9 @@ __mmplayer_check_codec_info(mmplayer_t *player, const char *klass, GstCaps *caps goto DONE; } - mm_attrs_get_int_by_name(player->attrs, "audio_codec_type", &codec_type); - - LOGD("audio codec type: %d", codec_type); - if (codec_type == MM_PLAYER_CODEC_TYPE_HW) { - /* sw codec will be skipped */ - for (idx = 0; player->ini.audiocodec_element_sw[idx][0] != '\0'; idx++) { - if (strstr(factory_name, player->ini.audiocodec_element_sw[idx])) { - LOGW("skipping sw acodec:[%s] by codec type", factory_name); - ret = GST_AUTOPLUG_SELECT_SKIP; - goto DONE; - } - } - } else if (codec_type == MM_PLAYER_CODEC_TYPE_SW) { - /* hw codec will be skipped */ - if (strcmp(player->ini.audiocodec_element_hw, "") && - g_strrstr(factory_name, player->ini.audiocodec_element_hw)) { - LOGW("skipping hw acodec:[%s] by codec type", factory_name); - ret = GST_AUTOPLUG_SELECT_SKIP; - goto DONE; - } - } + /* FIXME: If HW audio decoder is selected, related resource have to be acquired here. + And need to consider the multi-track audio content. + There is no HW audio decoder in public. */ /* set stream information */ if (!player->audiodec_linked) @@ -7003,27 +7063,6 @@ __mmplayer_check_codec_info(mmplayer_t *player, const char *klass, GstCaps *caps } else if (g_strrstr(klass, "Codec/Decoder/Video")) { - mm_attrs_get_int_by_name(player->attrs, "video_codec_type", &codec_type); - - LOGD("video codec type: %d", codec_type); - if (codec_type == MM_PLAYER_CODEC_TYPE_HW) { - /* sw codec is skipped */ - for (idx = 0; player->ini.videocodec_element_sw[idx][0] != '\0'; idx++) { - if (strstr(factory_name, player->ini.videocodec_element_sw[idx])) { - LOGW("skipping sw vcodec:[%s] by codec type", factory_name); - ret = GST_AUTOPLUG_SELECT_SKIP; - goto DONE; - } - } - } else if (codec_type == MM_PLAYER_CODEC_TYPE_SW) { - /* hw codec is skipped */ - if (g_strrstr(factory_name, player->ini.videocodec_element_hw)) { - LOGW("skipping hw vcodec:[%s] by codec type", factory_name); - ret = GST_AUTOPLUG_SELECT_SKIP; - goto DONE; - } - } - if ((strlen(player->ini.videocodec_element_hw) > 0) && (g_strrstr(factory_name, player->ini.videocodec_element_hw))) { @@ -7052,6 +7091,130 @@ DONE: return ret; } +GValueArray * +_mmplayer_gst_decode_autoplug_sort(GstElement *bin, + GstPad *pad, GstCaps *caps, GValueArray *factories, gpointer data) +{ +#define DEFAULT_IDX 0xFFFF +#define MIN_FACTORY_NUM 2 + mmplayer_t *player = (mmplayer_t *)data; + GValueArray *new_factories = NULL; + GValue val = { 0, }; + GstElementFactory *factory = NULL; + const gchar *klass = NULL; + gchar *factory_name = NULL; + guint hw_dec_idx = DEFAULT_IDX; + guint first_sw_dec_idx = DEFAULT_IDX; + guint last_sw_dec_idx = DEFAULT_IDX; + guint new_pos = DEFAULT_IDX; + guint rm_pos = DEFAULT_IDX; + int audio_codec_type; + int video_codec_type; + mmplayer_codec_type_e codec_type = MM_PLAYER_CODEC_TYPE_DEFAULT; + + if (factories->n_values < MIN_FACTORY_NUM) + return NULL; + + mm_attrs_get_int_by_name(player->attrs, MM_PLAYER_VIDEO_CODEC_TYPE, &video_codec_type); + mm_attrs_get_int_by_name(player->attrs, MM_PLAYER_AUDIO_CODEC_TYPE, &audio_codec_type); + +#ifdef __DEBUG__ + LOGD("num of factory : %d, codec type %d, %d", factories->n_values, video_codec_type, audio_codec_type); +#endif + for (int i = 0 ; i < factories->n_values ; i++) { + gchar *hw_dec_info = NULL; + gchar (*sw_dec_info)[PLAYER_INI_MAX_STRLEN] = {NULL, }; + + factory = g_value_get_object(g_value_array_get_nth(factories, i)); + if (!factory) { + LOGW("failed to get factory object"); + continue; + } + klass = gst_element_factory_get_klass(factory); + factory_name = GST_OBJECT_NAME(factory); + +#ifdef __DEBUG__ + LOGD("Klass [%s] Factory [%s]", klass, factory_name); +#endif + if (g_strrstr(klass, "Codec/Decoder/Audio")) { + if (!player->need_audio_dec_sorting) { + LOGD("sorting is not required"); + return NULL; + } + codec_type = audio_codec_type; + hw_dec_info = player->ini.audiocodec_element_hw; + sw_dec_info = player->ini.audiocodec_element_sw; + } else if (g_strrstr(klass, "Codec/Decoder/Video")) { + if (!player->need_video_dec_sorting) { + LOGD("sorting is not required"); + return NULL; + } + codec_type = video_codec_type; + hw_dec_info = player->ini.videocodec_element_hw; + sw_dec_info = player->ini.videocodec_element_sw; + } else { + continue; + } + + if (g_strrstr(factory_name, hw_dec_info)) { + hw_dec_idx = i; + } else { + for (int j = 0; sw_dec_info[j][0] != '\0'; j++) { + if (strstr(factory_name, sw_dec_info[j])) { + last_sw_dec_idx = i; + if (first_sw_dec_idx == DEFAULT_IDX) { + first_sw_dec_idx = i; + } + } + } + + if (first_sw_dec_idx == DEFAULT_IDX) + LOGW("unknown codec %s", factory_name); + } + } + + if (hw_dec_idx == DEFAULT_IDX || first_sw_dec_idx == DEFAULT_IDX) + return NULL; + + if (codec_type == MM_PLAYER_CODEC_TYPE_HW) { + if (hw_dec_idx < first_sw_dec_idx) + return NULL; + new_pos = first_sw_dec_idx; + rm_pos = hw_dec_idx + 1; + } else if (codec_type == MM_PLAYER_CODEC_TYPE_SW) { + if (last_sw_dec_idx < hw_dec_idx) + return NULL; + new_pos = last_sw_dec_idx + 1; + rm_pos = hw_dec_idx; + } else { + return NULL; + } + + /* change position - insert H/W decoder according to the new position */ + factory = g_value_get_object(g_value_array_get_nth(factories, hw_dec_idx)); + if (!factory) { + LOGW("failed to get factory object"); + return NULL; + } + new_factories = g_value_array_copy(factories); + g_value_init (&val, G_TYPE_OBJECT); + g_value_set_object (&val, factory); + g_value_array_insert(new_factories, new_pos, &val); + g_value_unset (&val); + g_value_array_remove(new_factories, rm_pos); /* remove previous H/W element */ + + for (int i = 0 ; i < new_factories->n_values ; i++) { + factory = g_value_get_object(g_value_array_get_nth(new_factories, i)); + if (factory) + LOGD("[Re-arranged] Klass [%s] Factory [%s]", + gst_element_factory_get_klass(factory), GST_OBJECT_NAME (factory)); + else + LOGE("[Re-arranged] failed to get factory object"); + } + + return new_factories; +} + gint _mmplayer_gst_decode_autoplug_select(GstElement *bin, GstPad *pad, GstCaps *caps, GstElementFactory *factory, gpointer data) @@ -7226,15 +7389,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); @@ -7264,7 +7426,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; } @@ -7275,7 +7436,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(); } @@ -7373,17 +7533,6 @@ __mmplayer_release_misc(mmplayer_t *player) MMPLAYER_RETURN_IF_FAIL(player); - player->video_decoded_cb = NULL; - player->video_decoded_cb_user_param = NULL; - player->video_stream_prerolled = false; - - player->audio_decoded_cb = NULL; - player->audio_decoded_cb_user_param = NULL; - player->audio_extract_opt = MM_PLAYER_AUDIO_EXTRACT_DEFAULT; - - player->audio_stream_changed_cb = NULL; - player->audio_stream_changed_cb_user_param = NULL; - player->sent_bos = FALSE; player->playback_rate = DEFAULT_PLAYBACK_RATE; @@ -7464,9 +7613,19 @@ __mmplayer_release_misc_post(mmplayer_t *player) MMPLAYER_FENTER(); /* player->pipeline is already released before. */ - MMPLAYER_RETURN_IF_FAIL(player); + player->video_decoded_cb = NULL; + player->video_decoded_cb_user_param = NULL; + player->video_stream_prerolled = false; + + player->audio_decoded_cb = NULL; + player->audio_decoded_cb_user_param = NULL; + player->audio_extract_opt = MM_PLAYER_AUDIO_EXTRACT_DEFAULT; + + player->audio_stream_changed_cb = NULL; + player->audio_stream_changed_cb_user_param = NULL; + mm_player_set_attribute((MMHandleType)player, NULL, "content_video_found", 0, NULL); /* clean found audio decoders */ @@ -7481,9 +7640,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"); @@ -7493,10 +7651,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 */ @@ -8517,7 +8674,7 @@ _mmplayer_get_streaming_buffering_time(MMHandleType hplayer, int *prebuffer_ms, } int -_mmplayer_set_codec_type(MMHandleType hplayer, mmplayer_stream_type_e stream_type, mmplayer_video_codec_type_e codec_type) +_mmplayer_set_codec_type(MMHandleType hplayer, mmplayer_stream_type_e stream_type, mmplayer_codec_type_e codec_type) { #define IDX_FIRST_SW_CODEC 0 mmplayer_t *player = (mmplayer_t *)hplayer; @@ -8534,7 +8691,10 @@ _mmplayer_set_codec_type(MMHandleType hplayer, mmplayer_stream_type_e stream_typ case MM_PLAYER_STREAM_TYPE_AUDIO: /* to support audio codec selection, codec info have to be added in ini file as below. audio codec element hw = xxxx - audio codec element sw = avdec */ + audio codec element sw = avdec + and in case of audio hw codec is supported and selected, + audio filter elements should be applied depending on the hw capabilities. + */ if (((codec_type == MM_PLAYER_CODEC_TYPE_HW) && (!strcmp(player->ini.audiocodec_element_hw, ""))) || ((codec_type == MM_PLAYER_CODEC_TYPE_SW) && @@ -8705,7 +8865,7 @@ _mmplayer_get_video_roi_area(MMHandleType hplayer, double *scale_x, double *scal int _mmplayer_set_client_pid(MMHandleType hplayer, int pid) { - mmplayer_t* player = (mmplayer_t*)hplayer; + mmplayer_t *player = (mmplayer_t *)hplayer; MMPLAYER_FENTER(); @@ -8720,6 +8880,75 @@ _mmplayer_set_client_pid(MMHandleType hplayer, int pid) return MM_ERROR_NONE; } +int +_mmplayer_is_audio_control_available(MMHandleType hplayer, mmplayer_audio_control_opt_e opt, bool *available) +{ + mmplayer_t *player = (mmplayer_t *)hplayer; + mmplayer_codec_type_e codec_type = MM_PLAYER_CODEC_TYPE_DEFAULT; + enum audio_element_id elem_id = MMPLAYER_A_NUM; + + MMPLAYER_FENTER(); + + MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED); + MMPLAYER_RETURN_VAL_IF_FAIL(available, MM_ERROR_INVALID_ARGUMENT); + + *available = true; + mm_attrs_get_int_by_name(player->attrs, MM_PLAYER_AUDIO_CODEC_TYPE, (int *)&codec_type); + + LOGD("current state %d, codec_type %d", MMPLAYER_CURRENT_STATE(player), codec_type); + + if (codec_type == MM_PLAYER_CODEC_TYPE_SW) + return MM_ERROR_NONE; + + /* in case of audio codec default type is HW */ + switch(opt) { + case MM_PLAYER_AUDIO_CONTROL_OPT_EFFECT: + if (player->ini.support_audio_effect) + return MM_ERROR_NONE; + elem_id = MMPLAYER_A_FILTER; + break; + case MM_PLAYER_AUDIO_CONTROL_OPT_REPLAYGAIN: + if (player->ini.support_replaygain_control) + return MM_ERROR_NONE; + elem_id = MMPLAYER_A_RGVOL; + break; + case MM_PLAYER_AUDIO_CONTROL_OPT_PITCH: + if (player->ini.support_pitch_control) + return MM_ERROR_NONE; + elem_id = MMPLAYER_A_PITCH; + break; + case MM_PLAYER_AUDIO_CONTROL_OPT_PCM_EXPORTING: + if (player->ini.support_audio_effect) + return MM_ERROR_NONE; + break; + /* default case handling is not required */ + } + + if (MMPLAYER_CURRENT_STATE(player) < MM_PLAYER_STATE_READY) { + LOGW("audio control option [%d] is not available", opt); + *available = false; + } else { + /* setting pcm exporting option is allowed before READY state */ + if (opt == MM_PLAYER_AUDIO_CONTROL_OPT_PCM_EXPORTING) + return MM_ERROR_PLAYER_INVALID_STATE; + + /* check whether the audio filter exist or not after READY state, + because the sw codec could be added during auto-plugging in some cases */ + if (!player->pipeline || + !player->pipeline->audiobin || + !player->pipeline->audiobin[elem_id].gst) { + LOGW("there is no audio elem [%d]", elem_id); + *available = false; + } + } + + LOGD("audio control opt %d, available %d", opt, *available); + + MMPLAYER_FLEAVE(); + + return MM_ERROR_NONE; +} + static gboolean __mmplayer_update_duration_value(mmplayer_t *player) { @@ -9017,11 +9246,12 @@ __mmplayer_set_file_uri(mmplayer_parse_profile_t *data, const char *uri) /* if no protocol prefix exist. check file existence and then give file:// as it's prefix */ if (ret == MM_ERROR_NONE) { - g_snprintf(data->uri, MM_MAX_URL_LEN, "file://%s", path); if (_mmplayer_is_sdp_file(path)) { LOGD("uri is actually a file but it's sdp file. giving it to rtspsrc"); + g_snprintf(data->uri, MM_MAX_URL_LEN, "rtsp-sdp://%s", path); data->uri_type = MM_PLAYER_URI_TYPE_URL_RTSP; } else { + g_snprintf(data->uri, MM_MAX_URL_LEN, "file://%s", path); data->uri_type = MM_PLAYER_URI_TYPE_FILE; } } else if (ret == MM_ERROR_PLAYER_PERMISSION_DENIED) {