[0.6.222] support codec type setting with u3
[platform/core/multimedia/libmm-player.git] / src / mm_player_priv.c
index 08c11fb..a15b493 100644 (file)
@@ -140,17 +140,10 @@ static int                __mmplayer_gst_create_text_pipeline(mmplayer_t *player);
 static int             __mmplayer_gst_create_video_sink_bin(mmplayer_t *player, GstCaps *caps, MMDisplaySurfaceType surface_type);
 static int             __mmplayer_gst_create_audio_sink_bin(mmplayer_t *player);
 static int             __mmplayer_gst_create_text_sink_bin(mmplayer_t *player);
-
-static void            __mmplayer_gst_decode_no_more_pads(GstElement *elem, gpointer data);
-static void            __mmplayer_gst_create_sinkbin(GstElement *decodebin, GstPad *pad, gpointer data);
-static void            __mmplayer_gst_decode_unknown_type(GstElement *elem,  GstPad *pad, GstCaps *caps, gpointer data);
-static gboolean __mmplayer_gst_decode_autoplug_continue(GstElement *bin,  GstPad *pad, GstCaps *caps,  gpointer data);
-static void __mmplayer_gst_decode_pad_removed(GstElement *elem,  GstPad *new_pad, gpointer data);
-static void __mmplayer_gst_decode_drained(GstElement *bin, gpointer data);
-static void    __mmplayer_pipeline_complete(GstElement *decodebin,  gpointer data);
+static void            __mmplayer_gst_create_sink_bin(GstElement *decodebin, GstPad *pad, GstCaps *ref_caps, gpointer data);
+static gboolean __mmplayer_create_sink_path(mmplayer_t *player, GstElement *combiner, mmplayer_track_type_e type, GstCaps *caps);
 static gboolean __mmplayer_is_midi_type(gchar *str_caps);
 static gboolean __mmplayer_is_only_mp3_type(gchar *str_caps);
-static void    __mmplayer_set_audio_attrs(mmplayer_t *player, GstCaps *caps);
 
 static gboolean        __mmplayer_update_subtitle(GstElement *object, GstBuffer *buffer, GstPad *pad, gpointer data);
 static void            __mmplayer_release_misc(mmplayer_t *player);
@@ -178,8 +171,9 @@ 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 gboolean __mmplayer_deactivate_combiner(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);
 static guint32 _mmplayer_convert_fourcc_string_to_value(const gchar *format_name);
@@ -557,7 +551,7 @@ ALREADY_GOING:
        return MM_ERROR_PLAYER_NO_OP;
 }
 
-static int __mmplayer_acquire_hw_resource(mmplayer_t *player, mmplayer_resource_type_e type)
+int _mmplayer_acquire_hw_resource(mmplayer_t *player, mmplayer_resource_type_e type)
 {
        int rm_ret = MM_RESOURCE_MANAGER_ERROR_NONE;
        mm_resource_manager_res_type_e rm_res_type = MM_RESOURCE_MANAGER_RES_TYPE_MAX;
@@ -676,12 +670,7 @@ __mmplayer_initialize_gapless_play(mmplayer_t *player)
 
        /* clean found audio decoders */
        if (player->audio_decoders) {
-               GList *a_dec = player->audio_decoders;
-               for (; a_dec; a_dec = g_list_next(a_dec)) {
-                       gchar *name = a_dec->data;
-                       MMPLAYER_FREEIF(name);
-               }
-               g_list_free(player->audio_decoders);
+               g_list_free_full(player->audio_decoders, (GDestroyNotify)g_free);
                player->audio_decoders = NULL;
        }
 
@@ -690,6 +679,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)
 {
@@ -706,10 +705,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;
                }
@@ -749,6 +745,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;
@@ -758,11 +790,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);
@@ -865,7 +892,7 @@ __mmplayer_gst_selector_update_start_time(mmplayer_t *player, mmplayer_track_typ
 
        for (idx = MM_PLAYER_TRACK_TYPE_AUDIO; idx < MM_PLAYER_TRACK_TYPE_TEXT; idx++) {
                if ((player->gapless.update_segment[idx] == TRUE) ||
-                       !(player->selector[idx].event_probe_id)) {
+                       !(player->track[idx].event_probe_id)) {
 #ifdef __DEBUG__
                        LOGW("[%d] skip", idx);
 #endif
@@ -936,7 +963,7 @@ __mmplayer_gst_selector_event_probe(GstPad *pad, GstPadProbeInfo *info, gpointer
                GST_EVENT_TYPE(event) != GST_EVENT_QOS)
                return ret;
 
-       MMPLAYER_GST_GET_CAPS_INFO(pad, caps, str, name, caps_ret);
+       MMPLAYER_GST_GET_CAPS_INFO_FROM_PAD(pad, caps, str, name, caps_ret);
        if (!caps_ret)
                goto ERROR;
 
@@ -1120,6 +1147,35 @@ EXIT:
 }
 
 static GstElement *
+__mmplayer_gst_make_concat(mmplayer_t *player, main_element_id_e elem_idx)
+{
+       GstElement *pipeline = NULL;
+       GstElement *concat = NULL;
+
+       MMPLAYER_FENTER();
+       MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline && player->pipeline->mainbin, NULL);
+
+       concat = gst_element_factory_make("concat", NULL);
+       if (!concat) {
+               LOGE("failed to create concat");
+               return NULL;
+       }
+
+       LOGD("Create concat [%d] element", elem_idx);
+
+       player->pipeline->mainbin[elem_idx].id = elem_idx;
+       player->pipeline->mainbin[elem_idx].gst = concat;
+
+       gst_element_set_state(concat, GST_STATE_PAUSED);
+
+       pipeline = player->pipeline->mainbin[MMPLAYER_M_PIPE].gst;
+       gst_bin_add(GST_BIN(pipeline), concat);
+
+       MMPLAYER_FLEAVE();
+       return concat;
+}
+
+static GstElement *
 __mmplayer_gst_make_selector(mmplayer_t *player, main_element_id_e elem_idx, mmplayer_track_type_e stream_type)
 {
        GstElement *pipeline = NULL;
@@ -1139,14 +1195,14 @@ __mmplayer_gst_make_selector(mmplayer_t *player, main_element_id_e elem_idx, mmp
        player->pipeline->mainbin[elem_idx].id = elem_idx;
        player->pipeline->mainbin[elem_idx].gst = selector;
 
-       /* player->selector[stream_type].active_pad_index = DEFAULT_TRACK; */
+       /* player->track[stream_type].active_track_index = DEFAULT_TRACK; */
 
        srcpad = gst_element_get_static_pad(selector, "src");
 
        LOGD("blocking %s:%s", GST_DEBUG_PAD_NAME(srcpad));
-       player->selector[stream_type].block_id = gst_pad_add_probe(srcpad, GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM,
+       player->track[stream_type].block_id = gst_pad_add_probe(srcpad, GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM,
                __mmplayer_gst_selector_blocked, NULL, NULL);
-       player->selector[stream_type].event_probe_id = gst_pad_add_probe(srcpad, GST_PAD_PROBE_TYPE_EVENT_BOTH|GST_PAD_PROBE_TYPE_EVENT_FLUSH,
+       player->track[stream_type].event_probe_id = gst_pad_add_probe(srcpad, GST_PAD_PROBE_TYPE_EVENT_BOTH|GST_PAD_PROBE_TYPE_EVENT_FLUSH,
                __mmplayer_gst_selector_event_probe, player, NULL);
 
        gst_element_set_state(selector, GST_STATE_PAUSED);
@@ -1164,7 +1220,7 @@ void
 _mmplayer_gst_decode_pad_added(GstElement *elem, GstPad *pad, gpointer data)
 {
        mmplayer_t *player = (mmplayer_t *)data;
-       GstElement *selector = NULL;
+       GstElement *combiner = NULL;
        GstCaps *caps = NULL;
        GstStructure *str = NULL;
        const gchar *name = NULL;
@@ -1182,7 +1238,7 @@ _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);
+       MMPLAYER_GST_GET_CAPS_INFO_FROM_PAD(pad, caps, str, name, caps_ret);
        if (!caps_ret)
                goto ERROR;
 
@@ -1208,7 +1264,7 @@ _mmplayer_gst_decode_pad_added(GstElement *elem, GstPad *pad, gpointer data)
                LOGD("surface type : %d", stype);
 
                if (MMPLAYER_IS_MS_BUFF_SRC(player)) {
-                       __mmplayer_gst_create_sinkbin(elem, pad, player);
+                       __mmplayer_gst_create_sink_bin(elem, pad, caps, player);
                        goto DONE;
                }
 
@@ -1219,8 +1275,13 @@ _mmplayer_gst_decode_pad_added(GstElement *elem, GstPad *pad, gpointer data)
                        goto DONE;
                }
 
-               LOGD("video selector is required");
-               elem_idx = MMPLAYER_M_V_INPUT_SELECTOR;
+               if (MMPLAYER_USE_DECODEBIN(player)) {
+                       LOGD("video selector is required");
+                       elem_idx = MMPLAYER_M_V_INPUT_SELECTOR;
+               } else {
+                       LOGD("video concat is required");
+                       elem_idx = MMPLAYER_M_V_CONCAT;
+               }
                stream_type = MM_PLAYER_TRACK_TYPE_VIDEO;
        } else if (strstr(name, "audio")) {
                gint samplerate = 0;
@@ -1229,7 +1290,7 @@ _mmplayer_gst_decode_pad_added(GstElement *elem, GstPad *pad, gpointer data)
                if (MMPLAYER_IS_MS_BUFF_SRC(player) || player->build_audio_offload) {
                        if (player->build_audio_offload)
                                player->no_more_pad = TRUE; /* remove state holder */
-                       __mmplayer_gst_create_sinkbin(elem, pad, player);
+                       __mmplayer_gst_create_sink_bin(elem, pad, caps, player);
                        goto DONE;
                }
 
@@ -1240,14 +1301,23 @@ _mmplayer_gst_decode_pad_added(GstElement *elem, GstPad *pad, gpointer data)
                        __mmplayer_gst_make_fakesink(player, pad, name);
                        goto DONE;
                }
-
-               LOGD("audio selector is required");
-               elem_idx = MMPLAYER_M_A_INPUT_SELECTOR;
+               if (MMPLAYER_USE_DECODEBIN(player)) {
+                       LOGD("audio selector is required");
+                       elem_idx = MMPLAYER_M_A_INPUT_SELECTOR;
+               } else {
+                       LOGD("audio concat is required");
+                       elem_idx = MMPLAYER_M_A_CONCAT;
+               }
                stream_type = MM_PLAYER_TRACK_TYPE_AUDIO;
 
        } else if (strstr(name, "text")) {
-               LOGD("text selector is required");
-               elem_idx = MMPLAYER_M_T_INPUT_SELECTOR;
+               if (MMPLAYER_USE_DECODEBIN(player)) {
+                       LOGD("text selector is required");
+                       elem_idx = MMPLAYER_M_T_INPUT_SELECTOR;
+               } else {
+                       LOGD("text concat is required");
+                       elem_idx = MMPLAYER_M_T_CONCAT;
+               }
                stream_type = MM_PLAYER_TRACK_TYPE_TEXT;
        } else {
                LOGE("invalid caps info");
@@ -1255,32 +1325,41 @@ _mmplayer_gst_decode_pad_added(GstElement *elem, GstPad *pad, gpointer data)
        }
 
        /* check selector and create it */
-       if (!(selector = player->pipeline->mainbin[elem_idx].gst)) {
-               selector = __mmplayer_gst_make_selector(player, elem_idx, stream_type);
-               if (!selector)
+       if (!(combiner = player->pipeline->mainbin[elem_idx].gst)) {
+               if (MMPLAYER_USE_DECODEBIN(player))
+                       combiner = __mmplayer_gst_make_selector(player, elem_idx, stream_type);
+               else
+                       combiner = __mmplayer_gst_make_concat(player, elem_idx);
+
+               if (!combiner)
                        goto ERROR;
                first_track = TRUE;
        } else {
-               LOGD("input-selector is already created.");
+               LOGD("Combiner element is already created.");
        }
 
        /* link */
-       sinkpad = gst_element_get_request_pad(selector, "sink_%u");
+       sinkpad = gst_element_get_request_pad(combiner, "sink_%u");
 
        LOGD("pad link: %s:%s - %s:%s", GST_DEBUG_PAD_NAME(pad), GST_DEBUG_PAD_NAME(sinkpad));
 
        if (gst_pad_link(pad, sinkpad) != GST_PAD_LINK_OK) {
-               LOGE("failed to link selector");
-               gst_object_unref(GST_OBJECT(selector));
+               LOGE("failed to link combiner");
+               gst_object_unref(GST_OBJECT(combiner));
                goto ERROR;
        }
 
        if (first_track) {
-               LOGD("this track will be activated");
-               g_object_set(selector, "active-pad", sinkpad, NULL);
+               if (MMPLAYER_USE_DECODEBIN(player)) {
+                       LOGD("this track will be activated");
+                       g_object_set(combiner, "active-pad", sinkpad, NULL);
+               }
        }
 
-       _mmplayer_track_update_selector_info(player, stream_type, sinkpad);
+       if (MMPLAYER_USE_DECODEBIN(player))
+               _mmplayer_track_update_stream(player, stream_type, sinkpad);
+       else
+               __mmplayer_create_sink_path(player, combiner, stream_type, caps);
 
 DONE:
 ERROR:
@@ -1297,7 +1376,7 @@ ERROR:
 }
 
 static gboolean
-__mmplayer_create_sink_path(mmplayer_t *player, GstElement *selector, mmplayer_track_type_e type)
+__mmplayer_create_sink_path(mmplayer_t *player, GstElement *combiner, mmplayer_track_type_e type, GstCaps *caps)
 {
        GstPad *srcpad = NULL;
 
@@ -1306,25 +1385,25 @@ __mmplayer_create_sink_path(mmplayer_t *player, GstElement *selector, mmplayer_t
 
        LOGD("type %d", type);
 
-       if (!selector) {
+       if (!combiner) {
                LOGD("there is no %d track", type);
                return TRUE;
        }
 
-       srcpad = gst_element_get_static_pad(selector, "src");
+       srcpad = gst_element_get_static_pad(combiner, "src");
        if (!srcpad) {
-               LOGE("failed to get srcpad from selector");
+               LOGE("failed to get srcpad from combiner");
                return FALSE;
        }
 
-       LOGD("got pad %s:%s from selector", GST_DEBUG_PAD_NAME(srcpad));
+       LOGD("got pad %s:%s from combiner", GST_DEBUG_PAD_NAME(srcpad));
 
-       __mmplayer_gst_create_sinkbin(selector, srcpad, player);
+       __mmplayer_gst_create_sink_bin(combiner, srcpad, caps, player);
 
        LOGD("unblocking %s:%s", GST_DEBUG_PAD_NAME(srcpad));
-       if (player->selector[type].block_id) {
-               gst_pad_remove_probe(srcpad, player->selector[type].block_id);
-               player->selector[type].block_id = 0;
+       if (player->track[type].block_id) {
+               gst_pad_remove_probe(srcpad, player->track[type].block_id);
+               player->track[type].block_id = 0;
        }
 
        if (srcpad) {
@@ -1344,21 +1423,21 @@ __mmplayer_set_decode_track_info(mmplayer_t *player, mmplayer_track_type_e type)
        MMPLAYER_FENTER();
        MMPLAYER_RETURN_IF_FAIL(player);
 
-       LOGD("type: %d, the num of track: %d", type, player->selector[type].total_track_num);
+       LOGD("type: %d, the num of track: %d", type, player->track[type].total_track_num);
 
        /* change track to active pad */
-       active_index = player->selector[type].active_pad_index;
+       active_index = player->track[type].active_track_index;
        if ((active_index != DEFAULT_TRACK) &&
                (__mmplayer_change_selector_pad(player, type, active_index) != MM_ERROR_NONE)) {
                LOGW("failed to change %d type track to %d", type, active_index);
-               player->selector[type].active_pad_index = DEFAULT_TRACK;
+               player->track[type].active_track_index = DEFAULT_TRACK;
                return;
        }
 
        if (type == MM_PLAYER_TRACK_TYPE_TEXT)
                mm_player_set_attribute((MMHandleType)player, NULL,
-                               "content_text_track_num", player->selector[type].total_track_num,
-                               "current_text_track_index", player->selector[type].active_pad_index, NULL);
+                               "content_text_track_num", player->track[type].total_track_num,
+                               "current_text_track_index", player->track[type].active_track_index, NULL);
 
        MMPLAYER_FLEAVE();
        return;
@@ -1385,16 +1464,17 @@ __mmplayer_create_audio_sink_path(mmplayer_t *player, GstElement *audio_selector
                }
 
                if (player->num_dynamic_pad == 0) /* FIXME: num_dynamic_pad is only for rtsp? */
-                       __mmplayer_pipeline_complete(NULL, player);
+                       _mmplayer_pipeline_complete(NULL, player);
 
                return TRUE;
        }
 
        /* apply the audio track information */
-       __mmplayer_set_decode_track_info(player, MM_PLAYER_TRACK_TYPE_AUDIO);
+       if (MMPLAYER_USE_DECODEBIN(player))
+               __mmplayer_set_decode_track_info(player, MM_PLAYER_TRACK_TYPE_AUDIO);
 
        /* create audio sink path */
-       if (!__mmplayer_create_sink_path(player, audio_selector, MM_PLAYER_TRACK_TYPE_AUDIO)) {
+       if (!__mmplayer_create_sink_path(player, audio_selector, MM_PLAYER_TRACK_TYPE_AUDIO, NULL)) {
                LOGE("failed to create audio sink path");
                return FALSE;
        }
@@ -1417,13 +1497,13 @@ __mmplayer_create_text_sink_path(mmplayer_t *player, GstElement *text_selector)
        /* apply the text track information */
        __mmplayer_set_decode_track_info(player, MM_PLAYER_TRACK_TYPE_TEXT);
 
-       if (player->selector[MM_PLAYER_TRACK_TYPE_TEXT].total_track_num > 0)
+       if (player->track[MM_PLAYER_TRACK_TYPE_TEXT].total_track_num > 0)
                player->has_closed_caption = TRUE;
 
        /* create text decode path */
        player->no_more_pad = TRUE;
 
-       if (!__mmplayer_create_sink_path(player, text_selector, MM_PLAYER_TRACK_TYPE_TEXT)) {
+       if (!__mmplayer_create_sink_path(player, text_selector, MM_PLAYER_TRACK_TYPE_TEXT, NULL)) {
                LOGE("failed to create text sink path");
                return FALSE;
        }
@@ -1456,8 +1536,8 @@ __mmplayer_gst_set_queue2_buffering(mmplayer_t *player)
        return TRUE;
 }
 
-static void
-__mmplayer_gst_decode_no_more_pads(GstElement *elem, gpointer data)
+void
+_mmplayer_gst_decode_no_more_pads(GstElement *elem, gpointer data)
 {
        mmplayer_t *player = NULL;
        GstElement *video_selector = NULL;
@@ -1498,7 +1578,7 @@ __mmplayer_gst_decode_no_more_pads(GstElement *elem, gpointer data)
        if (video_selector && !audio_selector && !text_selector)
                player->no_more_pad = TRUE;
 
-       if (!__mmplayer_create_sink_path(player, video_selector, MM_PLAYER_TRACK_TYPE_VIDEO))
+       if (!__mmplayer_create_sink_path(player, video_selector, MM_PLAYER_TRACK_TYPE_VIDEO, NULL))
                goto EXIT;
 
        /* create audio path followed by audio-select */
@@ -1512,11 +1592,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();
 }
 
@@ -1583,7 +1659,7 @@ EXIT:
 }
 
 static void
-__mmplayer_gst_create_sinkbin(GstElement *elem, GstPad *pad, gpointer data)
+__mmplayer_gst_create_sink_bin(GstElement *elem, GstPad *pad, GstCaps *ref_caps, gpointer data)
 {
        mmplayer_t *player = NULL;
        GstCaps *caps = NULL;
@@ -1601,10 +1677,14 @@ __mmplayer_gst_create_sinkbin(GstElement *elem, GstPad *pad, gpointer data)
        MMPLAYER_FENTER();
        MMPLAYER_RETURN_IF_FAIL(elem && pad);
        MMPLAYER_RETURN_IF_FAIL(player && player->pipeline && MMPLAYER_GET_ATTRS(player));
+       MMPLAYER_GST_GET_CAPS_INFO_FROM_PAD(pad, caps, str, name, caps_ret);
+       if (!caps_ret) {
+               MMPLAYER_GST_GET_CAPS_INFO(ref_caps, str, name, caps_ret);
+               if (!caps_ret)
+                       goto ERROR;
 
-       MMPLAYER_GST_GET_CAPS_INFO(pad, caps, str, name, caps_ret);
-       if (!caps_ret)
-               goto ERROR;
+               caps = gst_caps_ref(ref_caps);
+       }
 
        caps_str = gst_caps_to_string(caps);
 #ifdef __DEBUG__
@@ -1642,7 +1722,7 @@ __mmplayer_gst_create_sinkbin(GstElement *elem, GstPad *pad, gpointer data)
                        LOGD("display_surface_type (%d)", surface_type);
 
                        if ((surface_type == MM_DISPLAY_SURFACE_OVERLAY) &&
-                               (__mmplayer_acquire_hw_resource(player, MMPLAYER_RESOURCE_TYPE_VIDEO_OVERLAY) != MM_ERROR_NONE)) {
+                               (_mmplayer_acquire_hw_resource(player, MMPLAYER_RESOURCE_TYPE_VIDEO_OVERLAY) != MM_ERROR_NONE)) {
                                LOGE("failed to acquire video overlay resource");
                                goto ERROR;
                        }
@@ -1705,7 +1785,7 @@ __mmplayer_gst_create_sinkbin(GstElement *elem, GstPad *pad, gpointer data)
        LOGD("no more pads: %d, stream count dec : %d(num of dynamic pad)", player->no_more_pad, player->num_dynamic_pad);
 
        if ((player->no_more_pad) && (player->num_dynamic_pad == 0))
-               __mmplayer_pipeline_complete(NULL, player);
+               _mmplayer_pipeline_complete(NULL, player);
 
 ERROR:
 
@@ -2042,7 +2122,7 @@ _mmplayer_set_audio_only(MMHandleType hplayer, bool audio_only)
                        goto ERROR;
                }
        } else {
-               if (__mmplayer_acquire_hw_resource(player, MMPLAYER_RESOURCE_TYPE_VIDEO_OVERLAY) != MM_ERROR_NONE) {
+               if (_mmplayer_acquire_hw_resource(player, MMPLAYER_RESOURCE_TYPE_VIDEO_OVERLAY) != MM_ERROR_NONE) {
                        LOGE("failed to acquire video overlay resource");
                        goto ERROR;
                }
@@ -2195,7 +2275,7 @@ __mmplayer_gst_caps_notify_cb(GstPad *pad, GParamSpec *unused, gpointer data)
        if (!caps)
                return;
 
-       MMPLAYER_GST_GET_CAPS_INFO(pad, caps, str, name, caps_ret);
+       MMPLAYER_GST_GET_CAPS_INFO_FROM_PAD(pad, caps, str, name, caps_ret);
        if (!caps_ret)
                goto ERROR;
 
@@ -2485,7 +2565,7 @@ __mmplayer_gst_audio_deinterleave_no_more_pads(GstElement* object, gpointer data
        MMPLAYER_RETURN_IF_FAIL(player && player->pipeline && player->pipeline->mainbin);
 
        player->no_more_pad = TRUE;
-       __mmplayer_pipeline_complete(NULL, player);
+       _mmplayer_pipeline_complete(NULL, player);
 
        MMPLAYER_FLEAVE();
        return;
@@ -2538,13 +2618,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;
        };
 
@@ -2557,18 +2640,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 &&
@@ -2585,6 +2673,7 @@ __mmplayer_gst_set_openalsink_property(mmplayer_t *player)
        }
 
        MMPLAYER_FLEAVE();
+       return MM_ERROR_NONE;
 }
 
 static int
@@ -2722,10 +2811,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 */
@@ -3102,27 +3193,27 @@ _mmplayer_video_stream_release_bo(mmplayer_t *player, void *bo)
        LOGW("failed to find bo %p", bo);
        return ret;
 }
+static void
+__mmplayer_video_stream_bo_list_free(mmplayer_video_bo_info_t *tmp)
+{
+       if (!tmp)
+               return;
+
+       if (tmp->bo)
+               tbm_bo_unref(tmp->bo);
+       g_free(tmp);
+}
 
 static void
 __mmplayer_video_stream_destroy_bo_list(mmplayer_t *player)
 {
-       GList *l = NULL;
-
        MMPLAYER_FENTER();
        MMPLAYER_RETURN_IF_FAIL(player);
 
        MMPLAYER_VIDEO_BO_LOCK(player);
        if (player->video_bo_list) {
                LOGD("destroy video_bo_list : %d", g_list_length(player->video_bo_list));
-               for (l = g_list_first(player->video_bo_list); l; l = g_list_next(l)) {
-                       mmplayer_video_bo_info_t *tmp = (mmplayer_video_bo_info_t *)l->data;
-                       if (tmp) {
-                               if (tmp->bo)
-                                       tbm_bo_unref(tmp->bo);
-                               g_free(tmp);
-                       }
-               }
-               g_list_free(player->video_bo_list);
+               g_list_free_full(player->video_bo_list, (GDestroyNotify)__mmplayer_video_stream_bo_list_free);
                player->video_bo_list = NULL;
        }
        player->video_bo_size = 0;
@@ -3782,7 +3873,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();
@@ -4137,10 +4228,14 @@ __mmplayer_gst_create_pipeline(mmplayer_t *player)
        player->pipeline->mainbin = mainbin;
 
        /* create the source and decoder elements */
-       if (MMPLAYER_IS_MS_BUFF_SRC(player))
+       if (MMPLAYER_IS_MS_BUFF_SRC(player)) {
                ret = _mmplayer_gst_build_es_pipeline(player);
-       else
-               ret = _mmplayer_gst_build_pipeline(player);
+       } else {
+               if (MMPLAYER_USE_DECODEBIN(player))
+                       ret = _mmplayer_gst_build_pipeline(player); /* TEMP: previous pipeline, will be removed.*/
+               else
+                       ret = _mmplayer_gst_build_pipeline_with_src(player);
+       }
 
        if (ret != MM_ERROR_NONE) {
                LOGE("failed to create some elements");
@@ -4163,6 +4258,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;
 }
@@ -4196,13 +4292,14 @@ __mmplayer_gst_destroy_pipeline(mmplayer_t *player)
        MMPLAYER_FREEIF(player->type);
        player->no_more_pad = FALSE;
        player->num_dynamic_pad = 0;
-       player->demux_pad_index = 0;
 
        MMPLAYER_SUBTITLE_INFO_LOCK(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 +5001,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 +5018,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 +5025,11 @@ _mmplayer_destroy(MMHandleType handle)
        /* release attributes */
        _mmplayer_deconstruct_attribute(handle);
 
+       if (player->uri_info.uri_list) {
+               g_list_free_full(player->uri_info.uri_list, (GDestroyNotify)g_free);
+               player->uri_info.uri_list = NULL;
+       }
+
        /* release lock */
        g_mutex_clear(&player->fsink_lock);
 
@@ -4947,10 +5049,10 @@ 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;
 
        MMPLAYER_FENTER();
 
@@ -5003,7 +5105,6 @@ _mmplayer_realize(MMHandleType hplayer)
        player->is_subtitle_off = FALSE; /* set the subtitle ON default */
        player->video360_metadata.is_spherical = -1;
        player->is_openal_plugin_used = FALSE;
-       player->demux_pad_index = 0;
        player->subtitle_language_list = NULL;
        player->is_subtitle_force_drop = FALSE;
 
@@ -5058,6 +5159,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);
@@ -5410,28 +5512,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 +5554,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 +5592,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 +5800,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);
 
@@ -5774,8 +5882,8 @@ __mmplayer_is_only_mp3_type(gchar *str_caps)
        return FALSE;
 }
 
-static void
-__mmplayer_set_audio_attrs(mmplayer_t *player, GstCaps *caps)
+void
+_mmplayer_set_audio_attrs(mmplayer_t *player, GstCaps *caps)
 {
        GstStructure *caps_structure = NULL;
        gint samplerate = 0;
@@ -5845,7 +5953,6 @@ _mmplayer_typefind_have_type(GstElement *tf, guint probability,
        GstCaps *caps, gpointer data)
 {
        mmplayer_t *player = (mmplayer_t *)data;
-       GstPad *pad = NULL;
 
        MMPLAYER_FENTER();
 
@@ -5877,27 +5984,27 @@ _mmplayer_typefind_have_type(GstElement *tf, guint probability,
 
        __mmplayer_update_content_type_info(player);
 
-       pad = gst_element_get_static_pad(tf, "src");
-       if (!pad) {
-               LOGE("fail to get typefind src pad.");
-               return;
-       }
+       if (!player->pipeline->mainbin[MMPLAYER_M_AUTOPLUG].gst) {
+               GstPad *pad = NULL;
 
-       if (!_mmplayer_gst_create_decoder(player, pad, caps)) {
-               gboolean async = FALSE;
-               LOGE("failed to autoplug %s", player->type);
+               pad = gst_element_get_static_pad(tf, "src");
+               if (!pad) {
+                       LOGE("fail to get typefind src pad.");
+                       return;
+               }
 
-               mm_attrs_get_int_by_name(player->attrs, "profile_prepare_async", &async);
+               if (!_mmplayer_gst_create_decoder(player, pad, caps)) {
+                       gboolean async = FALSE;
+                       LOGE("failed to autoplug %s", player->type);
 
-               if (async && player->msg_posted == FALSE)
-                       __mmplayer_handle_missed_plugin(player);
+                       mm_attrs_get_int_by_name(player->attrs, "profile_prepare_async", &async);
 
+                       if (async && player->msg_posted == FALSE)
+                               __mmplayer_handle_missed_plugin(player);
+               }
+               gst_object_unref(GST_OBJECT(pad));
        }
-
-       gst_object_unref(GST_OBJECT(pad));
-
        MMPLAYER_FLEAVE();
-
        return;
 }
 
@@ -5922,20 +6029,24 @@ _mmplayer_gst_make_decodebin(mmplayer_t *player)
 
        /* no-more-pad pad handling signal */
        _mmplayer_add_signal_connection(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "no-more-pads",
-                                               G_CALLBACK(__mmplayer_gst_decode_no_more_pads), (gpointer)player);
+                                               G_CALLBACK(_mmplayer_gst_decode_no_more_pads), (gpointer)player);
 
        _mmplayer_add_signal_connection(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "pad-removed",
-                                               G_CALLBACK(__mmplayer_gst_decode_pad_removed), (gpointer)player);
+                                               G_CALLBACK(_mmplayer_gst_decode_pad_removed), (gpointer)player);
 
        /* This signal is emitted when a pad for which there is no further possible
           decoding is added to the decodebin.*/
        _mmplayer_add_signal_connection(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "unknown-type",
-                                               G_CALLBACK(__mmplayer_gst_decode_unknown_type), (gpointer)player);
+                                               G_CALLBACK(_mmplayer_gst_decode_unknown_type), (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-continue",
-                                               G_CALLBACK(__mmplayer_gst_decode_autoplug_continue), (gpointer)player);
+                                               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.*/
@@ -5944,7 +6055,7 @@ _mmplayer_gst_make_decodebin(mmplayer_t *player)
 
        /* This signal is emitted once decodebin has finished decoding all the data.*/
        _mmplayer_add_signal_connection(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "drained",
-                                               G_CALLBACK(__mmplayer_gst_decode_drained), (gpointer)player);
+                                               G_CALLBACK(_mmplayer_gst_decode_drained), (gpointer)player);
 
        /* This signal is emitted when a element is added to the bin.*/
        _mmplayer_add_signal_connection(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "element-added",
@@ -6212,8 +6323,8 @@ DONE:
        return MM_ERROR_NONE;
 }
 
-static void
-__mmplayer_pipeline_complete(GstElement *decodebin,  gpointer data)
+void
+_mmplayer_pipeline_complete(GstElement *decodebin, gpointer data)
 {
        mmplayer_t *player = (mmplayer_t *)data;
 
@@ -6224,7 +6335,7 @@ __mmplayer_pipeline_complete(GstElement *decodebin,  gpointer data)
        /* remove fakesink. */
        if (!_mmplayer_gst_remove_fakesink(player,
                                &player->pipeline->mainbin[MMPLAYER_M_SRC_FAKESINK])) {
-               /* NOTE : __mmplayer_pipeline_complete() can be called several time. because
+               /* NOTE : _mmplayer_pipeline_complete() can be called several time. because
                 * signaling mechanism(pad-added, no-more-pad, new-decoded-pad) from various
                 * source element are not same. To overcome this situation, this function will called
                 * several places and several times. Therefore, this is not an error case.
@@ -6398,10 +6509,91 @@ ERROR:
        return FALSE;
 }
 
+static void
+__mmplayer_remove_sinkpad (const GValue *item, gpointer user_data)
+{
+       GstPad *sinkpad = g_value_get_object (item);
+       GstElement *element = GST_ELEMENT(user_data);
+       LOGD("(%s)element release request pad(%s)", GST_ELEMENT_NAME(element), GST_PAD_NAME(sinkpad));
+       gst_element_release_request_pad(element, GST_PAD(sinkpad));
+}
+
+static gboolean
+__mmplayer_deactivate_combiner(mmplayer_t *player, mmplayer_track_type_e type)
+{
+       mmplayer_gst_element_t *sinkbin = NULL;
+       main_element_id_e concatId = MMPLAYER_M_NUM;
+       main_element_id_e sinkId = MMPLAYER_M_NUM;
+       gboolean send_notice = FALSE;
+       GstElement *element;
+       GstIterator *iter;
+
+       MMPLAYER_FENTER();
+       MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
+
+       LOGD("type %d", type);
+
+       switch (type) {
+       case MM_PLAYER_TRACK_TYPE_AUDIO:
+               concatId = MMPLAYER_M_A_CONCAT;
+               sinkId = MMPLAYER_A_BIN;
+               sinkbin = player->pipeline->audiobin;
+               break;
+       case MM_PLAYER_TRACK_TYPE_VIDEO:
+               concatId = MMPLAYER_M_V_CONCAT;
+               sinkId = MMPLAYER_V_BIN;
+               sinkbin = player->pipeline->videobin;
+               send_notice = TRUE;
+               break;
+       case MM_PLAYER_TRACK_TYPE_TEXT:
+               concatId = MMPLAYER_M_T_CONCAT;
+               sinkId = MMPLAYER_T_BIN;
+               sinkbin = player->pipeline->textbin;
+               break;
+       default:
+               LOGE("requested type is not supportable");
+               return FALSE;
+               break;
+       }
+
+       element = player->pipeline->mainbin[concatId].gst;
+       if (!element)
+               return TRUE;
+
+       if ((sinkbin) && (sinkbin[sinkId].gst)) {
+               GstPad *srcpad = gst_element_get_static_pad(element, "src");
+               GstPad *sinkpad = gst_element_get_static_pad(sinkbin[sinkId].gst, "sink");
+               if (srcpad && sinkpad) {
+                       /* after getting drained signal there is no data flows, so no need to do pad_block */
+                       LOGD("unlink %s:%s, %s:%s", GST_DEBUG_PAD_NAME(srcpad), GST_DEBUG_PAD_NAME(sinkpad));
+                       gst_pad_unlink(srcpad, sinkpad);
+
+                       /* send custom event to sink pad to handle it at video sink */
+                       if (send_notice) {
+                               LOGD("send custom event to sinkpad");
+                               GstStructure *s = gst_structure_new_empty("tizen/flush-buffer");
+                               GstEvent *event = gst_event_new_custom(GST_EVENT_CUSTOM_DOWNSTREAM, s);
+                               gst_pad_send_event(sinkpad, event);
+                       }
+               }
+               gst_object_unref(srcpad);
+               gst_object_unref(sinkpad);
+       }
+
+       LOGD("release concat request pad");
+       /* release and unref requests pad from the selector */
+       iter = gst_element_iterate_sink_pads(element);
+       while (gst_iterator_foreach(iter, __mmplayer_remove_sinkpad, element) == GST_ITERATOR_RESYNC)
+               gst_iterator_resync(iter);
+       gst_iterator_free(iter);
+
+       return TRUE;
+}
+
 static gboolean
 __mmplayer_deactivate_selector(mmplayer_t *player, mmplayer_track_type_e type)
 {
-       mmplayer_selector_t *selector = &player->selector[type];
+       mmplayer_track_t *selector = &player->track[type];
        mmplayer_gst_element_t *sinkbin = NULL;
        main_element_id_e selectorId = MMPLAYER_M_NUM;
        main_element_id_e sinkId = MMPLAYER_M_NUM;
@@ -6472,11 +6664,12 @@ __mmplayer_deactivate_selector(mmplayer_t *player, mmplayer_track_type_e type)
                LOGD("selector release");
 
                /* release and unref requests pad from the selector */
-               for (n = 0; n < selector->channels->len; n++) {
-                       GstPad *sinkpad = g_ptr_array_index(selector->channels, n);
+               for (n = 0; n < selector->streams->len; n++) {
+                       GstPad *sinkpad = g_ptr_array_index(selector->streams, n);
                        gst_element_release_request_pad((player->pipeline->mainbin[selectorId].gst), sinkpad);
                }
-               g_ptr_array_set_size(selector->channels, 0);
+
+               g_ptr_array_set_size(selector->streams, 0);
 
                gst_element_set_state(player->pipeline->mainbin[selectorId].gst, GST_STATE_NULL);
                gst_bin_remove(GST_BIN_CAST(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst), player->pipeline->mainbin[selectorId].gst);
@@ -6494,11 +6687,20 @@ __mmplayer_deactivate_old_path(mmplayer_t *player)
        MMPLAYER_FENTER();
        MMPLAYER_RETURN_IF_FAIL(player);
 
-       if ((!__mmplayer_deactivate_selector(player, MM_PLAYER_TRACK_TYPE_AUDIO)) ||
-               (!__mmplayer_deactivate_selector(player, MM_PLAYER_TRACK_TYPE_VIDEO)) ||
-               (!__mmplayer_deactivate_selector(player, MM_PLAYER_TRACK_TYPE_TEXT))) {
-               LOGE("deactivate selector error");
-               goto ERROR;
+       if (MMPLAYER_USE_DECODEBIN(player)) {
+               if ((!__mmplayer_deactivate_selector(player, MM_PLAYER_TRACK_TYPE_AUDIO)) ||
+                       (!__mmplayer_deactivate_selector(player, MM_PLAYER_TRACK_TYPE_VIDEO)) ||
+                       (!__mmplayer_deactivate_selector(player, MM_PLAYER_TRACK_TYPE_TEXT))) {
+                       LOGE("deactivate selector error");
+                       goto ERROR;
+               }
+       } else {
+               if ((!__mmplayer_deactivate_combiner(player, MM_PLAYER_TRACK_TYPE_AUDIO)) ||
+                       (!__mmplayer_deactivate_combiner(player, MM_PLAYER_TRACK_TYPE_VIDEO)) ||
+                       (!__mmplayer_deactivate_combiner(player, MM_PLAYER_TRACK_TYPE_TEXT))) {
+                       LOGE("deactivate concat error");
+                       goto ERROR;
+               }
        }
 
        _mmplayer_track_destroy(player);
@@ -6510,9 +6712,7 @@ __mmplayer_deactivate_old_path(mmplayer_t *player)
                player->streamer = NULL;
        }
 
-       MMPLAYER_PLAYBACK_LOCK(player);
        MMPLAYER_GAPLESS_PLAY_THREAD_SIGNAL(player);
-
        MMPLAYER_FLEAVE();
        return;
 
@@ -6627,7 +6827,7 @@ _mmplayer_get_next_uri(MMHandleType hplayer, char **uri)
        if (num_of_list > 0) {
                gint uri_idx = player->uri_info.uri_idx;
 
-               if (uri_idx < num_of_list-1)
+               if (uri_idx < num_of_list - 1)
                        uri_idx++;
                else
                        uri_idx = 0;
@@ -6642,8 +6842,8 @@ _mmplayer_get_next_uri(MMHandleType hplayer, char **uri)
        return MM_ERROR_NONE;
 }
 
-static void
-__mmplayer_gst_decode_unknown_type(GstElement *elem,  GstPad *pad,
+void
+_mmplayer_gst_decode_unknown_type(GstElement *elem, GstPad *pad,
        GstCaps *caps, gpointer data)
 {
        mmplayer_t *player = (mmplayer_t *)data;
@@ -6664,9 +6864,9 @@ __mmplayer_gst_decode_unknown_type(GstElement *elem,  GstPad *pad,
        __mmplayer_check_not_supported_codec(player, klass, mime);
 }
 
-static gboolean
-__mmplayer_gst_decode_autoplug_continue(GstElement *bin,  GstPad *pad,
-       GstCaps *caps,  gpointer data)
+gboolean
+_mmplayer_gst_decode_autoplug_continue(GstElement *bin, GstPad *pad,
+       GstCaps *caps, gpointer data)
 {
        mmplayer_t *player = (mmplayer_t *)data;
        const char *mime = NULL;
@@ -6720,7 +6920,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;
        }
@@ -6737,7 +6937,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;
        }
@@ -6914,7 +7114,7 @@ __mmplayer_can_build_audio_offload_path(mmplayer_t *player)
        }
        gst_object_unref(factory);
 
-       if (__mmplayer_acquire_hw_resource(player,
+       if (_mmplayer_acquire_hw_resource(player,
                        MMPLAYER_RESOURCE_TYPE_AUDIO_OFFLOAD) != MM_ERROR_NONE) {
                LOGE("failed to acquire audio offload decoder resource");
                goto DONE;
@@ -6941,8 +7141,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"))) {
@@ -6964,31 +7162,9 @@ __mmplayer_check_codec_info(mmplayer_t *player, const char *klass, GstCaps *caps
                                  And need to consider the multi-track audio content.
                          There is no HW audio decoder in public. */
 
-               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;
-                       }
-               }
-
                /* set stream information */
                if (!player->audiodec_linked)
-                       __mmplayer_set_audio_attrs(player, caps);
+                       _mmplayer_set_audio_attrs(player, caps);
 
                /* update codec info */
                player->not_supported_codec &= MISSING_PLUGIN_VIDEO;
@@ -6997,27 +7173,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))) {
 
@@ -7028,7 +7183,7 @@ __mmplayer_check_codec_info(mmplayer_t *player, const char *klass, GstCaps *caps
                                goto DONE;
                        }
 
-                       if (__mmplayer_acquire_hw_resource(player, MMPLAYER_RESOURCE_TYPE_VIDEO_DECODER) != MM_ERROR_NONE) {
+                       if (_mmplayer_acquire_hw_resource(player, MMPLAYER_RESOURCE_TYPE_VIDEO_DECODER) != MM_ERROR_NONE) {
                                LOGE("failed to acquire video decoder resource");
                                ret = GST_AUTOPLUG_SELECT_SKIP;
                                goto DONE;
@@ -7046,6 +7201,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)
@@ -7176,8 +7455,8 @@ DONE:
        return result;
 }
 
-static void
-__mmplayer_gst_decode_pad_removed(GstElement *elem,  GstPad *new_pad,
+void
+_mmplayer_gst_decode_pad_removed(GstElement *elem, GstPad *new_pad,
        gpointer data)
 {
        //mmplayer_t *player = (mmplayer_t *)data;
@@ -7200,8 +7479,38 @@ __mmplayer_gst_decode_pad_removed(GstElement *elem,  GstPad *new_pad,
        gst_caps_unref(caps);
 }
 
-static void
-__mmplayer_gst_decode_drained(GstElement *bin, gpointer data)
+void
+_mmplayer_gst_about_to_finish(GstElement *bin, gpointer data)
+{
+       mmplayer_t *player = (mmplayer_t *)data;
+
+       MMPLAYER_FENTER();
+       MMPLAYER_RETURN_IF_FAIL(player);
+
+       LOGD("got about to finish signal");
+
+       if (!MMPLAYER_CMD_TRYLOCK(player)) {
+               LOGW("Fail to get cmd lock");
+               return;
+       }
+
+       if (!__mmplayer_verify_gapless_play_path(player)) {
+               LOGD("decoding is finished.");
+               MMPLAYER_CMD_UNLOCK(player);
+               return;
+       }
+
+       _mmplayer_set_reconfigure_state(player, TRUE);
+       MMPLAYER_CMD_UNLOCK(player);
+
+       MMPLAYER_POST_MSG(player, MM_MESSAGE_GAPLESS_CONSTRUCTION, NULL);
+       __mmplayer_deactivate_old_path(player);
+
+       MMPLAYER_FLEAVE();
+}
+
+void
+_mmplayer_gst_decode_drained(GstElement *bin, gpointer data)
 {
        mmplayer_t *player = (mmplayer_t *)data;
        GstIterator *iter = NULL;
@@ -7213,22 +7522,21 @@ __mmplayer_gst_decode_drained(GstElement *bin, gpointer data)
        MMPLAYER_FENTER();
        MMPLAYER_RETURN_IF_FAIL(player);
 
-       LOGD("__mmplayer_gst_decode_drained");
+       LOGD("got drained signal");
 
        if (!MMPLAYER_CMD_TRYLOCK(player)) {
                LOGW("Fail to get cmd lock");
                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);
@@ -7258,7 +7566,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;
        }
@@ -7269,7 +7576,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();
 }
@@ -7293,6 +7599,16 @@ _mmplayer_gst_element_added(GstElement *bin, GstElement *element, gpointer data)
                gchar *selected = NULL;
                selected = g_strdup(GST_ELEMENT_NAME(element));
                player->audio_decoders = g_list_append(player->audio_decoders, selected);
+
+               /* update codec info */
+               player->not_supported_codec &= MISSING_PLUGIN_VIDEO;
+               player->can_support_codec |= FOUND_PLUGIN_AUDIO;
+               player->audiodec_linked = 1;
+       } else if (g_strrstr(klass, "Codec/Decoder/Video")) {
+               /* update codec info */
+               player->not_supported_codec &= MISSING_PLUGIN_AUDIO;
+               player->can_support_codec |= FOUND_PLUGIN_VIDEO;
+               player->videodec_linked = 1;
        }
 
        if (g_strrstr(klass, "Demuxer/Adaptive")) {
@@ -7367,17 +7683,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;
 
@@ -7458,25 +7763,33 @@ __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 */
        if (player->audio_decoders) {
-               GList *a_dec = player->audio_decoders;
-               for (; a_dec; a_dec = g_list_next(a_dec)) {
-                       gchar *name = a_dec->data;
-                       MMPLAYER_FREEIF(name);
-               }
-               g_list_free(player->audio_decoders);
+               g_list_free_full(player->audio_decoders, (GDestroyNotify)g_free);
                player->audio_decoders = NULL;
        }
 
        /* 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) {
+               GList *tmp = NULL;
                original_uri = g_list_nth_data(player->uri_info.uri_list, 0);
+               tmp = g_list_remove_link(player->uri_info.uri_list, player->uri_info.uri_list);
+               g_list_free_full(tmp, (GDestroyNotify)g_free);
 
                if (!original_uri)
                        LOGW("failed to get original uri info");
@@ -7484,13 +7797,6 @@ __mmplayer_release_misc_post(mmplayer_t *player)
                mm_player_set_attribute((MMHandleType)player, NULL, "profile_uri",
                                original_uri, (original_uri) ? strlen(original_uri) : (0), NULL);
 
-               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;
        }
 
        /* clear the audio stream buffer list */
@@ -8022,6 +8328,44 @@ _mmplayer_set_external_subtitle_path(MMHandleType hplayer, const char *filepath)
 }
 
 static int
+__mmplayer_switch_stream(mmplayer_t *player, mmplayer_track_type_e type, int index)
+{
+       guint active_idx = 0;
+       GstStream *stream = NULL;
+       GList *streams = NULL;
+       GstEvent *ev = NULL;
+       GstCaps *caps = NULL;
+
+       LOGD("Switching Streams... type: %d, index: %d", type, index);
+
+       player->track[type].active_track_index = index;
+
+       for (int i = 0; i < MM_PLAYER_TRACK_TYPE_MAX; i++) {
+               /* FIXME: need to consider the non display type or audio only in case of MM_PLAYER_TRACK_TYPE_VIDEO */
+               if (player->track[i].total_track_num > 0) {
+                       active_idx = player->track[i].active_track_index;
+                       stream = g_ptr_array_index(player->track[i].streams, active_idx);
+                       streams = g_list_append (streams, (gchar *)gst_stream_get_stream_id(stream));
+                       LOGD("Selecting %d type stream : %s\n", i, gst_stream_get_stream_id(stream));
+
+                       if (i == MM_PLAYER_TRACK_TYPE_AUDIO) {
+                               caps = gst_stream_get_caps(stream);
+                               if (caps) {
+                                       _mmplayer_set_audio_attrs(player, caps);
+                                       gst_caps_unref(caps);
+                               }
+                       }
+               }
+       }
+
+       ev = gst_event_new_select_streams(streams);
+       gst_element_send_event(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, ev);
+       g_list_free(streams);
+
+       return MM_ERROR_NONE;
+}
+
+static int
 __mmplayer_change_selector_pad(mmplayer_t *player, mmplayer_track_type_e type, int index)
 {
        int result = MM_ERROR_NONE;
@@ -8057,7 +8401,7 @@ __mmplayer_change_selector_pad(mmplayer_t *player, mmplayer_track_type_e type, i
                goto EXIT;
        }
 
-       total_track_num = player->selector[type].total_track_num;
+       total_track_num = player->track[type].total_track_num;
        if (total_track_num <= 0) {
                result = MM_ERROR_PLAYER_NO_OP;
                LOGD("Language list is not available");
@@ -8097,7 +8441,10 @@ __mmplayer_change_selector_pad(mmplayer_t *player, mmplayer_track_type_e type, i
                gst_object_unref(sinkpad);
 
        if (type == MM_PLAYER_TRACK_TYPE_AUDIO)
-               __mmplayer_set_audio_attrs(player, caps);
+               _mmplayer_set_audio_attrs(player, caps);
+
+       if (caps)
+               gst_caps_unref(caps);
 
 EXIT:
        MMPLAYER_FREEIF(change_pad_name);
@@ -8114,7 +8461,6 @@ _mmplayer_change_track_language(MMHandleType hplayer, mmplayer_track_type_e type
        gint current_active_index = 0;
 
        GstState current_state = GST_STATE_VOID_PENDING;
-       GstEvent *event = NULL;
        gint64 time = 0;
 
        MMPLAYER_FENTER();
@@ -8125,13 +8471,13 @@ _mmplayer_change_track_language(MMHandleType hplayer, mmplayer_track_type_e type
        if (!player->pipeline) {
                LOGE("Track %d pre setting -> %d", type, index);
 
-               player->selector[type].active_pad_index = index;
+               player->track[type].active_track_index = index;
                goto EXIT;
        }
 
        mainbin = player->pipeline->mainbin;
 
-       current_active_index = player->selector[type].active_pad_index;
+       current_active_index = player->track[type].active_track_index;
 
        /*If index is same as running index no need to change the pad*/
        if (current_active_index == index)
@@ -8149,23 +8495,30 @@ _mmplayer_change_track_language(MMHandleType hplayer, mmplayer_track_type_e type
                goto EXIT;
        }
 
-       result = __mmplayer_change_selector_pad(player, type, index);
+       if (MMPLAYER_USE_DECODEBIN(player))
+               result = __mmplayer_change_selector_pad(player, type, index);
+       else
+               result = __mmplayer_switch_stream(player, type, index);
+
        if (result != MM_ERROR_NONE) {
-               LOGE("change selector pad error");
+               LOGE("failed to change track");
                goto EXIT;
        }
 
-       player->selector[type].active_pad_index = index;
+       player->track[type].active_track_index = index;
 
-       if (current_state == GST_STATE_PLAYING) {
-               event = gst_event_new_seek(player->playback_rate, GST_FORMAT_TIME,
-                       (GstSeekFlags)(GST_SEEK_FLAG_SEGMENT | GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_SKIP),
-                       GST_SEEK_TYPE_SET, time, GST_SEEK_TYPE_NONE, -1);
-               if (event) {
-                       _mmplayer_gst_send_event_to_sink(player, event);
-               } else {
-                       result = MM_ERROR_PLAYER_INTERNAL;
-                       goto EXIT;
+       if (MMPLAYER_USE_DECODEBIN(player)) {
+               GstEvent *event = NULL;
+               if (current_state == GST_STATE_PLAYING) {
+                       event = gst_event_new_seek(player->playback_rate, GST_FORMAT_TIME,
+                               (GstSeekFlags)(GST_SEEK_FLAG_SEGMENT | GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_SKIP),
+                               GST_SEEK_TYPE_SET, time, GST_SEEK_TYPE_NONE, -1);
+                       if (event) {
+                               _mmplayer_gst_send_event_to_sink(player, event);
+                       } else {
+                               result = MM_ERROR_PLAYER_INTERNAL;
+                               goto EXIT;
+                       }
                }
        }
 
@@ -8515,47 +8868,62 @@ _mmplayer_set_codec_type(MMHandleType hplayer, mmplayer_stream_type_e stream_typ
 {
 #define IDX_FIRST_SW_CODEC 0
        mmplayer_t *player = (mmplayer_t *)hplayer;
-       const char *attr_name = (stream_type == MM_PLAYER_STREAM_TYPE_AUDIO) ? (MM_PLAYER_AUDIO_CODEC_TYPE) : (MM_PLAYER_VIDEO_CODEC_TYPE);
+       int default_codec_type = MM_PLAYER_CODEC_TYPE_DEFAULT;
+       const char *attr_name = NULL;
+       const char *default_type = NULL;
+       const char *element_hw = NULL;
+       const char *element_sw = NULL;
 
        MMPLAYER_FENTER();
        MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
 
-       LOGD("ini setting : [a][h:%s][s:%s] / [v][h:%s][s:%s]",
-               player->ini.audiocodec_element_hw, player->ini.audiocodec_element_sw[IDX_FIRST_SW_CODEC],
-               player->ini.videocodec_element_hw, player->ini.videocodec_element_sw[IDX_FIRST_SW_CODEC]);
+       LOGD("stream type: %d, codec_type: %d", stream_type, codec_type);
 
+       /* FIXME: player need to know whether the decoder exist or not about required codec type since 6.0*/
        switch (stream_type) {
        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
-          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) &&
-                        (!strcmp(player->ini.audiocodec_element_sw[IDX_FIRST_SW_CODEC], "")))) {
-                       LOGE("There is no audio codec info for codec_type %d", codec_type);
-                       return MM_ERROR_PLAYER_NO_OP;
-               }
-       break;
+               attr_name = MM_PLAYER_AUDIO_CODEC_TYPE;
+               default_type = player->ini.audiocodec_default_type;
+               element_hw = player->ini.audiocodec_element_hw;
+               element_sw = player->ini.audiocodec_element_sw[IDX_FIRST_SW_CODEC];
+               break;
        case MM_PLAYER_STREAM_TYPE_VIDEO:
-       /* to support video codec selection, codec info have to be added in ini file as below.
-          video codec element hw = omx
-          video codec element sw = avdec */
-               if (((codec_type == MM_PLAYER_CODEC_TYPE_HW) &&
-                        (!strcmp(player->ini.videocodec_element_hw, ""))) ||
-                       ((codec_type == MM_PLAYER_CODEC_TYPE_SW) &&
-                        (!strcmp(player->ini.videocodec_element_sw[IDX_FIRST_SW_CODEC], "")))) {
-                       LOGE("There is no video codec info for codec_type %d", codec_type);
-                       return MM_ERROR_PLAYER_NO_OP;
-               }
-       break;
+               attr_name = MM_PLAYER_VIDEO_CODEC_TYPE;
+               default_type = player->ini.videocodec_default_type;
+               element_hw = player->ini.videocodec_element_hw;
+               element_sw = player->ini.videocodec_element_sw[IDX_FIRST_SW_CODEC];
+               break;
        default:
                LOGE("Invalid stream type %s", MMPLAYER_STREAM_TYPE_GET_NAME(stream_type));
                return MM_ERROR_COMMON_INVALID_ARGUMENT;
-       break;
+               break;
+       }
+
+       LOGD("default setting: [%s][%s][h:%s][s:%s]", attr_name, default_type, element_hw, element_sw);
+
+       if (!strcmp(default_type, "sw"))
+               default_codec_type = MM_PLAYER_CODEC_TYPE_SW;
+       else
+               default_codec_type = MM_PLAYER_CODEC_TYPE_HW;
+
+       if (codec_type == MM_PLAYER_CODEC_TYPE_DEFAULT)
+               codec_type = default_codec_type;
+
+       /* to support codec selection, codec info have to be added in ini file.
+          in case of hw codec is selected, filter elements should be applied
+          depending on the hw capabilities. */
+       if (codec_type != default_codec_type) {
+               if (((codec_type == MM_PLAYER_CODEC_TYPE_HW) && (!strcmp(element_hw, ""))) ||
+                       ((codec_type == MM_PLAYER_CODEC_TYPE_SW) && (!strcmp(element_sw, "")))) {
+                       LOGE("There is no codec for type %d", codec_type);
+                       return MM_ERROR_PLAYER_NO_OP;
+               }
+
+               LOGD("sorting is required");
+               if (stream_type == MM_PLAYER_STREAM_TYPE_AUDIO)
+                       player->need_audio_dec_sorting = TRUE;
+               else
+                       player->need_video_dec_sorting = TRUE;
        }
 
        LOGD("update %s codec_type to %d", attr_name, codec_type);
@@ -9083,11 +9451,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) {