[0.6.216] fix svace issue
[platform/core/multimedia/libmm-player.git] / src / mm_player_priv.c
index c955e14..1978703 100644 (file)
@@ -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;
                }
@@ -1513,11 +1519,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 +2541,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 +2563,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 +2596,7 @@ __mmplayer_gst_set_openalsink_property(mmplayer_t *player)
        }
 
        MMPLAYER_FLEAVE();
+       return MM_ERROR_NONE;
 }
 
 static int
@@ -2723,10 +2734,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 */
@@ -3455,19 +3468,20 @@ __mmplayer_gst_set_videosink_property(mmplayer_t *player, MMDisplaySurfaceType s
 
        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 (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);
        }
-       LOGD("surface type : %d, videosink factory name is %s use-tbm : %d", surface_type, factory_name, use_tbm);
 
        mm_attrs_get_int_by_name(attrs, MM_PLAYER_GAPLESS_MODE, &gapless);
        if (gapless > 0) {
@@ -3782,7 +3796,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();
@@ -4202,7 +4216,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);
@@ -4904,6 +4920,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");
@@ -4918,9 +4937,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);
@@ -4928,6 +4944,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);
 
@@ -4947,11 +4973,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 */
@@ -5035,6 +5063,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)
@@ -5410,28 +5455,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*/
@@ -5448,9 +5497,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);
@@ -5484,8 +5535,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:
@@ -5692,8 +5743,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);
 
@@ -5937,6 +5988,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",
@@ -6234,8 +6289,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);
 
@@ -6511,9 +6565,7 @@ __mmplayer_deactivate_old_path(mmplayer_t *player)
                player->streamer = NULL;
        }
 
-       MMPLAYER_PLAYBACK_LOCK(player);
        MMPLAYER_GAPLESS_PLAY_THREAD_SIGNAL(player);
-
        MMPLAYER_FLEAVE();
        return;
 
@@ -6698,13 +6750,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;
@@ -6728,7 +6773,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;
        }
@@ -6745,7 +6790,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;
        }
@@ -6949,8 +6994,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"))) {
@@ -6968,27 +7011,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)
@@ -7001,27 +7026,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))) {
 
@@ -7050,6 +7054,122 @@ 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));
+               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 */
+       new_factories = g_value_array_copy(factories);
+       factory = g_value_get_object(g_value_array_get_nth(factories, hw_dec_idx));
+       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)
@@ -7224,15 +7344,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);
@@ -7262,7 +7381,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;
        }
@@ -7273,7 +7391,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();
 }
@@ -7371,17 +7488,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;
 
@@ -7462,9 +7568,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 */
@@ -7479,9 +7595,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");
 
@@ -7491,10 +7606,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 */
@@ -8515,7 +8629,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;
@@ -8532,7 +8646,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) &&
@@ -8703,7 +8820,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();
 
@@ -8718,6 +8835,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)
 {
@@ -9015,11 +9201,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) {