[1.0.2] fix wrong condition
[platform/core/multimedia/libmm-player.git] / src / mm_player_gst.c
index 154e97e..234170c 100644 (file)
 |  FUNCTION DEFINITIONS                                                                                                                                                |
 |                                                                                                                                                                                      |
 ========================================================================================== */
-#ifdef __DEBUG__
-static void
-print_tag(const GstTagList *list, const gchar *tag, gpointer unused)
-{
-       gint i, count;
-
-       count = gst_tag_list_get_tag_size(list, tag);
-
-       LOGD("count = %d", count);
-
-       for (i = 0; i < count; i++) {
-               gchar *str;
-
-               if (gst_tag_get_type(tag) == G_TYPE_STRING) {
-                       if (!gst_tag_list_get_string_index(list, tag, i, &str))
-                               g_assert_not_reached();
-               } else {
-                       str = g_strdup_value_contents(gst_tag_list_get_value_index(list, tag, i));
-               }
-
-               if (i == 0)
-                       g_print("  %15s: %s", gst_tag_get_nick(tag), str);
-               else
-                       g_print("                 : %s", str);
-
-               g_free(str);
-       }
-}
-#endif
 
 static gboolean
 __mmplayer_check_error_posted_from_activated_track(mmplayer_t *player, gchar *src_element_name)
@@ -329,17 +300,17 @@ __mmplayer_gst_handle_resource_error(mmplayer_t *player, int code, GstMessage *m
                break;
        case GST_RESOURCE_ERROR_NOT_FOUND:
        case GST_RESOURCE_ERROR_OPEN_READ:
-               if (MMPLAYER_IS_HTTP_STREAMING(player) || MMPLAYER_IS_HTTP_LIVE_STREAMING(player)
-                       || MMPLAYER_IS_RTSP_STREAMING(player)) {
+               if (MMPLAYER_IS_STREAMING(player)) {
                        trans_err = MM_ERROR_PLAYER_STREAMING_CONNECTION_FAIL;
                        break;
                }
        case GST_RESOURCE_ERROR_READ:
-               if (MMPLAYER_IS_HTTP_STREAMING(player) || MMPLAYER_IS_HTTP_LIVE_STREAMING(player)
-                       || MMPLAYER_IS_RTSP_STREAMING(player)) {
+               if (MMPLAYER_IS_STREAMING(player)) {
                        trans_err = MM_ERROR_PLAYER_STREAMING_FAIL;
                        break;
-               } else if (message != NULL && message->src != NULL) {
+               }
+
+               if (message != NULL && message->src != NULL) {
                        storage_state_e storage_state = STORAGE_STATE_UNMOUNTABLE;
                        mmplayer_path_type_e path_type = MMPLAYER_PATH_MAX;
 
@@ -424,7 +395,7 @@ __mmplayer_handle_gst_error(mmplayer_t *player, GstMessage *message, GError *err
        MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
        MMPLAYER_RETURN_VAL_IF_FAIL(error, FALSE);
 
-       /* NOTE : do somthing necessary inside of __gst_handle_XXX_error. not here */
+       /* NOTE : do something necessary inside of __gst_handle_XXX_error. not here */
 
        memset(&msg_param, 0, sizeof(MMMessageParamType));
 
@@ -448,7 +419,7 @@ __mmplayer_handle_gst_error(mmplayer_t *player, GstMessage *message, GError *err
 
                msg_param.data = (void *)error->message;
 
-               LOGE("-Msg src : [%s]   Domain : [%s]   Error : [%s]  Code : [%d] is tranlated to error code : [0x%x]",
+               LOGE("-Msg src : [%s]   Domain : [%s]   Error : [%s]  Code : [%d] is translated to error code : [0x%x]",
                        msg_src_element, g_quark_to_string(error->domain), error->message, error->code, msg_param.code);
        }
 
@@ -484,27 +455,19 @@ __mmplayer_handle_gst_error(mmplayer_t *player, GstMessage *message, GError *err
 }
 
 static gboolean
-__mmplayer_handle_streaming_error(mmplayer_t *player, GstMessage *message)
+__mmplayer_handle_streaming_error(mmplayer_t *player, GstMessage *message, GError *error)
 {
        LOGD("\n");
-       MMMessageParamType msg_param;
+       MMMessageParamType msg_param = {0, };
        gchar *msg_src_element = NULL;
-       GstStructure *s = NULL;
-       guint error_id = 0;
-       gchar *error_string = NULL;
 
        MMPLAYER_FENTER();
 
        MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
        MMPLAYER_RETURN_VAL_IF_FAIL(message, FALSE);
+       MMPLAYER_RETURN_VAL_IF_FAIL(error, FALSE);
 
-       s = gst_structure_copy(gst_message_get_structure(message));
-
-
-       if (!gst_structure_get_uint(s, "error_id", &error_id))
-               error_id = MMPLAYER_STREAMING_ERROR_NONE;
-
-       switch (error_id) {
+       switch (error->code) {
        case MMPLAYER_STREAMING_ERROR_UNSUPPORTED_AUDIO:
                msg_param.code = MM_ERROR_PLAYER_STREAMING_UNSUPPORTED_AUDIO;
                break;
@@ -642,14 +605,12 @@ __mmplayer_handle_streaming_error(mmplayer_t *player, GstMessage *message)
                break;
        default:
                {
-                       gst_structure_free(s);
                        return MM_ERROR_PLAYER_STREAMING_FAIL;
                }
        }
 
-       error_string = g_strdup(gst_structure_get_string(s, "error_string"));
-       if (error_string)
-               msg_param.data = (void *)error_string;
+       if (error->message)
+               msg_param.data = (void *)(error->message);
 
        if (message->src) {
                msg_src_element = GST_ELEMENT_NAME(GST_ELEMENT_CAST(message->src));
@@ -668,9 +629,6 @@ __mmplayer_handle_streaming_error(mmplayer_t *player, GstMessage *message)
                LOGD("skip error post because it's sent already.");
        }
 
-       gst_structure_free(s);
-       MMPLAYER_FREEIF(error_string);
-
        MMPLAYER_FLEAVE();
        return TRUE;
 
@@ -743,7 +701,7 @@ __mmplayer_gst_extract_tag_from_msg(mmplayer_t *player, GstMessage *msg)
                        if (!gst_buffer_map(buffer, &info, GST_MAP_READ)) {\
                                LOGD("failed to get image data from tag");\
                                gst_sample_unref(sample);\
-                               return FALSE;\
+                               break;\
                        } \
                        SECURE_LOGD("update album cover data : %p, size : %zu", info.data, info.size);\
                        MMPLAYER_FREEIF(player->album_art);\
@@ -808,6 +766,11 @@ __mmplayer_gst_extract_tag_from_msg(mmplayer_t *player, GstMessage *msg)
                if (gst_tag_list_get_date(tag_list, gsttag, &date)) {\
                        if (date != NULL) {\
                                string = g_strdup_printf("%d", g_date_get_year(date));\
+                               if (string == NULL) {\
+                                       LOGD("failed to get date/time from tag");\
+                                       g_date_free(date);\
+                                       break;\
+                               } \
                                mm_player_set_attribute((MMHandleType)player, NULL,\
                                                playertag, string, strlen(string), NULL); \
                                SECURE_LOGD("metainfo year : %s", string);\
@@ -822,6 +785,11 @@ __mmplayer_gst_extract_tag_from_msg(mmplayer_t *player, GstMessage *msg)
                if (gst_tag_list_get_date_time(tag_list, gsttag, &datetime)) {\
                        if (datetime != NULL) {\
                                string = g_strdup_printf("%d", gst_date_time_get_year(datetime));\
+                               if (string == NULL) {\
+                                       LOGD("failed to get year from tag");\
+                                       gst_date_time_unref(datetime);\
+                                       break;\
+                               } \
                                mm_player_set_attribute((MMHandleType)player, NULL,\
                                                playertag, string, strlen(string), NULL); \
                                SECURE_LOGD("metainfo year : %s", string);\
@@ -914,7 +882,24 @@ __mmplayer_gst_extract_tag_from_msg(mmplayer_t *player, GstMessage *msg)
        return TRUE;
 }
 
-/* if retval is FALSE, it will be dropped for perfomance. */
+
+static mmplayer_track_type_e
+__mmplayer_convert_gst_stream_type_to_track_type (GstStreamType stype)
+{
+       switch (stype) {
+       case GST_STREAM_TYPE_AUDIO:
+               return MM_PLAYER_TRACK_TYPE_AUDIO;
+       case GST_STREAM_TYPE_VIDEO:
+               return MM_PLAYER_TRACK_TYPE_VIDEO;
+       case GST_STREAM_TYPE_TEXT:
+               return MM_PLAYER_TRACK_TYPE_TEXT;
+       default:
+               LOGD("not supported stream stype");
+               return MM_PLAYER_TRACK_TYPE_MAX;
+       }
+}
+
+/* if retval is FALSE, it will be dropped for performance. */
 static gboolean
 __mmplayer_gst_check_useful_message(mmplayer_t *player, GstMessage *message)
 {
@@ -941,10 +926,12 @@ __mmplayer_gst_check_useful_message(mmplayer_t *player, GstMessage *message)
        case GST_MESSAGE_ASYNC_DONE:
        case GST_MESSAGE_STATE_CHANGED:
                /* we only handle messages from pipeline */
+               MMPLAYER_RECONFIGURE_LOCK(player);
                if ((message->src == (GstObject *)player->pipeline->mainbin[MMPLAYER_M_PIPE].gst) && (!player->gapless.reconfigure))
                        retval = TRUE;
                else
                        retval = FALSE;
+               MMPLAYER_RECONFIGURE_UNLOCK(player);
                break;
        case GST_MESSAGE_BUFFERING:
        {
@@ -996,7 +983,9 @@ __mmplayer_gst_check_useful_message(mmplayer_t *player, GstMessage *message)
 
                LOGD("GST_MESSAGE_STREAMS_SELECTED");
                player->no_more_pad = TRUE;
-               _mmplayer_pipeline_complete(NULL, player);
+               _mmplayer_set_reconfigure_state(player, FALSE);
+               if (!MMPLAYER_IS_ADAPTIVE_STREAMING(player))
+                       _mmplayer_pipeline_complete(NULL, player);
                retval = TRUE;
                break;
        }
@@ -1018,14 +1007,22 @@ __mmplayer_update_buffer_setting(mmplayer_t *player, GstMessage *buffering_msg)
 
        _mmplayer_gst_get_position(player, &pos_nsec);  /* to update player->last_position */
 
-       if (MMPLAYER_IS_HTTP_STREAMING(player)) {
+       if (MMPLAYER_IS_HTTP_STREAMING(player))
                data_size = player->http_content_size;
-       }
 
        _mm_player_streaming_buffering(player->streamer, buffering_msg, data_size, player->last_position, player->duration);
-       _mm_player_streaming_sync_property(player->streamer, player->pipeline->mainbin[MMPLAYER_M_AUTOPLUG].gst);
+       if (!player->streamer->is_adaptive_streaming) {
+               _mm_player_streaming_sync_property(player->streamer, player->pipeline->mainbin[MMPLAYER_M_AUTOPLUG].gst);
+               return;
+       }
 
-       return;
+       /* adaptivedemux2 is used for buffering in uridecodebin3 */
+       if (!player->streamer->buffering_req.is_pre_buffering) {
+               LOGD("adaptive> set rebuffer time : %d ms", player->streamer->buffering_req.rebuffer_time);
+               g_object_set(player->pipeline->mainbin[MMPLAYER_M_ADAPTIVE_DEMUX].gst,
+                       "low-watermark-time", (guint64)(player->streamer->buffering_req.rebuffer_time * GST_MSECOND),
+                       NULL);
+       }
 }
 
 static int
@@ -1294,7 +1291,7 @@ __mmplayer_gst_pending_seek(mmplayer_t *player)
 
        ret = _mmplayer_gst_set_position(player, player->pending_seek.pos, FALSE);
        if (ret != MM_ERROR_NONE)
-               LOGE("failed to seek pending postion. just keep staying current position.");
+               LOGE("failed to seek pending position. just keep staying current position.");
 
        player->pending_seek.is_pending = false;
 
@@ -1371,7 +1368,7 @@ __mmplayer_gst_handle_eos_message(mmplayer_t *player, GstMessage *msg)
 
        MMPLAYER_FENTER();
 
-       /* NOTE : EOS event is comming multiple time. watch out it */
+       /* NOTE : EOS event is coming multiple time. watch out it */
        /* check state. we only process EOS when pipeline state goes to PLAYING */
        if (!(player->cmd == MMPLAYER_COMMAND_START || player->cmd == MMPLAYER_COMMAND_RESUME)) {
                LOGD("EOS received on non-playing state. ignoring it");
@@ -1440,12 +1437,12 @@ __mmplayer_gst_handle_error_message(mmplayer_t *player, GstMessage *msg)
                /* Note : the streaming error from the streaming source is handled
                 *       using __mmplayer_handle_streaming_error.
                 */
-               __mmplayer_handle_streaming_error(player, msg);
+               __mmplayer_handle_streaming_error(player, msg, error);
 
                /* dump state of all element */
                _mmplayer_dump_pipeline_state(player);
        } else {
-               /* traslate gst error code to msl error code. then post it
+               /* translate gst error code to msl error code. then post it
                 * to application if needed
                 */
                __mmplayer_handle_gst_error(player, msg, error);
@@ -1544,8 +1541,8 @@ __mmplayer_gst_handle_buffering_message(mmplayer_t *player, GstMessage *msg)
                                        player->seek_state = MMPLAYER_SEEK_NONE;
                                        MMPLAYER_POST_MSG(player, MM_MESSAGE_SEEK_COMPLETED, NULL);
                                } else if (MMPLAYER_TARGET_STATE(player) == MM_PLAYER_STATE_PLAYING) {
-                                       /* Considering the async state trasition in case of RTSP.
-                                          After getting state change gst msg, seek cmpleted msg will be posted. */
+                                       /* Considering the async state transition in case of RTSP.
+                                          After getting state change gst msg, seek completed msg will be posted. */
                                        player->seek_state = MMPLAYER_SEEK_COMPLETED;
                                }
                        }
@@ -1584,7 +1581,6 @@ static void
 __mmplayer_gst_handle_state_message(mmplayer_t *player, GstMessage *msg)
 {
        mmplayer_gst_element_t *mainbin;
-       const GValue *voldstate, *vnewstate, *vpending;
        GstState oldstate = GST_STATE_NULL;
        GstState newstate = GST_STATE_NULL;
        GstState pending = GST_STATE_NULL;
@@ -1598,20 +1594,7 @@ __mmplayer_gst_handle_state_message(mmplayer_t *player, GstMessage *msg)
        if (msg->src != (GstObject *)mainbin[MMPLAYER_M_PIPE].gst)
                return;
 
-       /* get state info from msg */
-       voldstate = gst_structure_get_value(gst_message_get_structure(msg), "old-state");
-       vnewstate = gst_structure_get_value(gst_message_get_structure(msg), "new-state");
-       vpending = gst_structure_get_value(gst_message_get_structure(msg), "pending-state");
-
-       if (!voldstate || !vnewstate) {
-               LOGE("received msg has wrong format.");
-               return;
-       }
-
-       oldstate = (GstState)voldstate->data[0].v_int;
-       newstate = (GstState)vnewstate->data[0].v_int;
-       if (vpending)
-               pending = (GstState)vpending->data[0].v_int;
+       gst_message_parse_state_changed(msg, &oldstate, &newstate, &pending);
 
        LOGD("state changed [%s] : %s ---> %s     final : %s",
                GST_OBJECT_NAME(GST_MESSAGE_SRC(msg)),
@@ -1628,7 +1611,7 @@ __mmplayer_gst_handle_state_message(mmplayer_t *player, GstMessage *msg)
                        retVal = _mmplayer_gst_set_position(player, player->pending_seek.pos, TRUE);
 
                        if (MM_ERROR_NONE != retVal)
-                               LOGE("failed to seek pending postion. just keep staying current position.");
+                               LOGE("failed to seek pending position. just keep staying current position.");
 
                        player->pending_seek.is_pending = false;
                }
@@ -1671,7 +1654,7 @@ __mmplayer_gst_handle_state_message(mmplayer_t *player, GstMessage *msg)
                {
                        if (MMPLAYER_IS_STREAMING(player)) {
                                // managed prepare async case when buffering is completed
-                               // pending state should be reset otherwise, it's still playing even though it's resumed after bufferging.
+                               // pending state should be reset otherwise, it's still playing even though it's resumed after buffering.
                                if ((MMPLAYER_CURRENT_STATE(player) != MM_PLAYER_STATE_PLAYING) ||
                                        (MMPLAYER_PENDING_STATE(player) == MM_PLAYER_STATE_PLAYING))
                                        MMPLAYER_SET_STATE(player, MM_PLAYER_STATE_PLAYING);
@@ -1786,13 +1769,13 @@ __mmplayer_gst_handle_element_message(mmplayer_t *player, GstMessage *msg)
        }
 
        /* custom message for RTSP attribute :
-               RTSP case, buffer is not come from server before PLAYING state. However,we have to get attribute after PAUSE state chaged.
+               RTSP case, buffer is not come from server before PLAYING state. However,we have to get attribute after PAUSE state changed.
                sdp which has contents info is received when rtsp connection is opened.
                extract duration ,codec info , resolution from sdp and get it by GstMessage */
        if (!strcmp(structure_name, "rtspsrc_properties")) {
-               gchar *audio_codec = NULL;
-               gchar *video_codec = NULL;
-               gchar *video_frame_size = NULL;
+               g_autofree gchar *audio_codec = NULL;
+               g_autofree gchar *video_codec = NULL;
+               g_autofree gchar *video_frame_size = NULL;
 
                gst_structure_get(gst_message_get_structure(msg),
                                        "rtsp_duration", G_TYPE_UINT64, &player->duration, NULL);
@@ -1847,6 +1830,9 @@ __mmplayer_gst_handle_async_done_message(mmplayer_t *player, GstMessage *msg)
                return;
 
        if (player->seek_state == MMPLAYER_SEEK_IN_PROGRESS) {
+               if (player->is_external_subtitle_present)
+                       _mmplayer_sync_subtitle_pipeline(player);
+
                if (MMPLAYER_TARGET_STATE(player) == MM_PLAYER_STATE_PAUSED) {
                        player->seek_state = MMPLAYER_SEEK_NONE;
                        MMPLAYER_POST_MSG(player, MM_MESSAGE_SEEK_COMPLETED, NULL);
@@ -1894,6 +1880,7 @@ __mmplayer_gst_handle_async_done_message(mmplayer_t *player, GstMessage *msg)
        return;
 }
 
+#ifdef __DEBUG__
 static void
 __mmplayer_print_tag_foreach(const GstTagList *tags, const gchar *tag, gpointer user_data)
 {
@@ -1913,59 +1900,38 @@ __mmplayer_print_tag_foreach(const GstTagList *tags, const gchar *tag, gpointer
        g_free(str);
        g_value_unset(&val);
 }
+#endif
 
 static void
 __mmplayer_dump_collection(GstStreamCollection * collection)
 {
        guint i = 0;
+#ifdef __DEBUG__
        GstTagList *tags = NULL;
+#endif
        GstCaps *caps = NULL;
 
        for (i = 0; i < gst_stream_collection_get_size(collection); i++) {
                GstStream *stream = gst_stream_collection_get_stream(collection, i);
-               LOGD ("collection: Stream %u type %s flags 0x%x\n", i,
+               LOGD ("collection: [%u] Stream, type: %s, flags 0x%x\n", i,
                                gst_stream_type_get_name(gst_stream_get_stream_type(stream)),
                                gst_stream_get_stream_flags(stream));
                LOGD ("  ID: %s\n", gst_stream_get_stream_id(stream));
 
                caps = gst_stream_get_caps(stream);
                if (caps) {
-                       gchar *caps_str = gst_caps_to_string(caps);
-                       LOGD ("  caps: %s\n", caps_str);
-                       g_free(caps_str);
+                       MMPLAYER_LOG_GST_CAPS_TYPE(caps);
                        gst_caps_unref(caps);
                }
 
+#ifdef __DEBUG__
                tags = gst_stream_get_tags(stream);
                if (tags) {
                        LOGD ("  tags:\n");
                        gst_tag_list_foreach(tags, __mmplayer_print_tag_foreach, GUINT_TO_POINTER(MMPLAYER_TAG_INDENT));
                        gst_tag_list_unref(tags);
                }
-       }
-}
-
-static void
-__mmplayer_stream_notify_cb(GstStreamCollection *collection,
-                       GstStream *stream, GParamSpec *pspec, gpointer data)
-{
-       LOGD ("Got stream-notify from stream %s for %s (collection %p)\n",
-                               gst_stream_get_stream_id(stream), pspec->name, collection);
-       if (g_str_equal(pspec->name, "caps")) {
-               GstCaps *caps = gst_stream_get_caps(stream);
-               gchar *caps_str = gst_caps_to_string(caps);
-               LOGD (" New caps: %s\n", caps_str);
-               g_free(caps_str);
-               gst_caps_unref(caps);
-       }
-
-       if (g_str_equal (pspec->name, "tags")) {
-               GstTagList *tags = gst_stream_get_tags(stream);
-               if (tags) {
-                       LOGD ("  tags:\n");
-                       gst_tag_list_foreach(tags, __mmplayer_print_tag_foreach, GUINT_TO_POINTER(MMPLAYER_TAG_INDENT));
-                       gst_tag_list_unref(tags);
-               }
+#endif
        }
 }
 
@@ -2081,15 +2047,6 @@ __mmplayer_gst_bus_msg_callback(GstMessage *msg, gpointer data)
                gst_message_parse_stream_collection(msg, &collection);
                if (collection) {
                        __mmplayer_dump_collection(collection);
-                       if (player->collection && player->stream_notify_id) {
-                               g_signal_handler_disconnect(player->collection, player->stream_notify_id);
-                               player->stream_notify_id = 0;
-                       }
-                       gst_object_replace((GstObject **)&player->collection, (GstObject *)collection);
-                       if (player->collection) {
-                               player->stream_notify_id = g_signal_connect(player->collection, "stream-notify",
-                                                       (GCallback)__mmplayer_stream_notify_cb, player);
-                       }
                        gst_object_unref(collection);
                }
        } break;
@@ -2100,14 +2057,28 @@ __mmplayer_gst_bus_msg_callback(GstMessage *msg, gpointer data)
 
                gst_message_parse_streams_selected(msg, &collection);
                if (collection) {
-                       guint i = 0, len = 0;
-                       len = gst_message_streams_selected_get_size(msg);
-                       for (i = 0; i < len; i++) {
+                       guint len = gst_message_streams_selected_get_size(msg);
+                       for (guint i = 0; i < len; i++) {
                                GstStream *stream = gst_message_streams_selected_get_stream(msg, i);
-                               LOGD ("  Stream #%d : %s\n", i, gst_stream_get_stream_id(stream));
+                               mmplayer_track_type_e type = __mmplayer_convert_gst_stream_type_to_track_type(
+                                                       gst_stream_get_stream_type(stream));
+                               if (type == MM_PLAYER_TRACK_TYPE_MAX) {
+                                       LOGD("not supported track type");
+                                       gst_object_unref(stream);
+                                       break;
+                               }
+                               LOGD("  Stream #%d : %s\n", i, gst_stream_get_stream_id(stream));
+                               if (player->track[type].active_track_index == INVALID_TRACK_INDEX) {
+                                       int stream_index = INVALID_TRACK_INDEX;
+                                       if (_mmplayer_get_track_index(player, type, stream, &stream_index) == MM_ERROR_NONE) {
+                                               player->track[type].active_track_index = stream_index;
+                                               LOGD("selected this stream, update active idx : %d",
+                                                               player->track[type].active_track_index);
+                                       }
+                               }
                                gst_object_unref(stream);
                        }
-                       gst_object_unref (collection);
+                       gst_object_unref(collection);
                }
        } break;
 
@@ -2166,7 +2137,7 @@ __mmplayer_gst_bus_sync_callback(GstBus *bus, GstMessage *message, gpointer data
                                LOGE("TAGS received from element \"%s\".",
                                GST_STR_NULL(GST_ELEMENT_NAME(GST_MESSAGE_SRC(message))));
 
-                               gst_tag_list_foreach(tags, print_tag, NULL);
+                               gst_tag_list_foreach(tags, __mmplayer_print_tag_foreach, GUINT_TO_POINTER(MMPLAYER_TAG_INDENT));
                                gst_tag_list_unref(tags);
                                tags = NULL;
                        }
@@ -2399,9 +2370,6 @@ __mmplayer_gst_create_es_decoder(mmplayer_t *player, mmplayer_stream_type_e type
                return FALSE;
        }
 
-       mainbin[elem_id].id = elem_id;
-       mainbin[elem_id].gst = decodebin;
-
        /* raw pad handling signal */
        _mmplayer_add_signal_connection(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "pad-added",
                                                                                G_CALLBACK(_mmplayer_gst_decode_pad_added), (gpointer)player);
@@ -2442,6 +2410,10 @@ __mmplayer_gst_create_es_decoder(mmplayer_t *player, mmplayer_stream_type_e type
        gst_object_unref(GST_OBJECT(sinkpad));
 
        gst_element_sync_state_with_parent(decodebin);
+
+       mainbin[elem_id].id = elem_id;
+       mainbin[elem_id].gst = decodebin;
+
        MMPLAYER_FLEAVE();
        return TRUE;
 
@@ -2449,11 +2421,10 @@ ERROR:
        if (sinkpad)
                gst_object_unref(GST_OBJECT(sinkpad));
 
-       if (mainbin[elem_id].gst) {
-               gst_element_set_state(mainbin[elem_id].gst, GST_STATE_NULL);
-               gst_bin_remove(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), mainbin[elem_id].gst);
-               gst_object_unref(mainbin[elem_id].gst);
-               mainbin[elem_id].gst = NULL;
+       if (decodebin) {
+               gst_element_set_state(decodebin, GST_STATE_NULL);
+               if (!gst_bin_remove(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), decodebin))
+                       gst_object_unref(decodebin);
        }
 
        MMPLAYER_FLEAVE();
@@ -2587,15 +2558,15 @@ __mmplayer_gst_create_es_path(mmplayer_t *player, mmplayer_stream_type_e type, G
 ERROR:
        if (mainbin[src_id].gst) {
                gst_element_set_state(mainbin[src_id].gst, GST_STATE_NULL);
-               gst_bin_remove(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), mainbin[src_id].gst);
-               gst_object_unref(mainbin[src_id].gst);
+               if (!gst_bin_remove(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), mainbin[src_id].gst))
+                       gst_object_unref(mainbin[src_id].gst);
                mainbin[src_id].gst = NULL;
        }
 
        if (mainbin[queue_id].gst) {
                gst_element_set_state(mainbin[queue_id].gst, GST_STATE_NULL);
-               gst_bin_remove(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), mainbin[queue_id].gst);
-               gst_object_unref(mainbin[queue_id].gst);
+               if (!gst_bin_remove(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), mainbin[queue_id].gst))
+                       gst_object_unref(mainbin[queue_id].gst);
                mainbin[queue_id].gst = NULL;
        }
 
@@ -2662,7 +2633,7 @@ __mmplayer_gst_rtp_dynamic_pad(GstElement *element, GstPad *pad, gpointer data)
 
 NEW_ELEMENT:
 
-       /* excute new_element if created*/
+       /* execute new_element if created*/
        if (new_element) {
                LOGD("adding new element to pipeline");
 
@@ -2691,7 +2662,7 @@ NEW_ELEMENT:
                gst_object_unref(sinkpad);
                sinkpad = NULL;
 
-               /* run. setting PLAYING here since streamming source is live source */
+               /* run. setting PLAYING here since streaming source is live source */
                MMPLAYER_ELEMENT_SET_STATE(new_element, GST_STATE_PLAYING);
        }
 
@@ -2734,11 +2705,11 @@ __mmplayer_gst_rtp_no_more_pads(GstElement *element,  gpointer data)
 
         * [1] audio and video will be dumped with filesink.
         * [2] autoplugging is done by just using pad caps.
-        * [3] typefinding has happend in audio but audiosink is created already before no-more-pad signal
+        * [3] typefinding has happened in audio but audiosink is created already before no-more-pad signal
         * and the video will be dumped via filesink.
         */
        if (player->num_dynamic_pad == 0) {
-               LOGD("it seems pad caps is directely used for autoplugging. removing fakesink now");
+               LOGD("it seems pad caps is directly used for autoplugging. removing fakesink now");
 
                if (!_mmplayer_gst_remove_fakesink(player,
                        &player->pipeline->mainbin[MMPLAYER_M_SRC_FAKESINK]))
@@ -2800,7 +2771,7 @@ __mmplayer_gst_make_rtsp_src(mmplayer_t *player)
        return element;
 }
 
-void __mmplayer_http_src_setup(GstElement *source, gpointer data)
+static void __mmplayer_http_src_setup(GstElement *source, gpointer data)
 {
 #define HTTP_SOURCE_BLOCK_SIZE (64 * 1024)
 
@@ -2816,29 +2787,24 @@ void __mmplayer_http_src_setup(GstElement *source, gpointer data)
 
        LOGD("source element %s", GST_ELEMENT_NAME(source));
 
-       /* get profile attribute */
        attrs = MMPLAYER_GET_ATTRS(player);
        if (!attrs) {
                LOGE("failed to get content attribute");
                return;
        }
 
-       /* get attribute */
        mm_attrs_get_string_by_name(attrs, "streaming_cookie", &cookies);
        mm_attrs_get_string_by_name(attrs, "streaming_user_agent", &user_agent);
 
        if (player->ini.http_timeout != DEFAULT_HTTP_TIMEOUT)
                http_timeout = player->ini.http_timeout;
 
-       /* get attribute */
        SECURE_LOGD("cookies : %s", cookies);
        SECURE_LOGD("user_agent :  %s", user_agent);
        LOGD("timeout : %d", http_timeout);
 
-       /* setting property to streaming source */
        g_object_set(G_OBJECT(source), "timeout", http_timeout, "blocksize", (unsigned long)(HTTP_SOURCE_BLOCK_SIZE), NULL);
 
-       /* parsing cookies */
        if ((cookie_list = _mmplayer_get_cookie_list((const char *)cookies))) {
                g_object_set(G_OBJECT(source), "cookies", cookie_list, NULL);
                g_strfreev(cookie_list);
@@ -2851,6 +2817,31 @@ void __mmplayer_http_src_setup(GstElement *source, gpointer data)
        return;
 }
 
+static void __mmplayer_rtsp_src_setup(GstElement *source, gpointer data)
+{
+       mmplayer_t *player = (mmplayer_t *)data;
+       gchar *user_agent = NULL;
+       MMHandleType attrs = 0;
+
+       MMPLAYER_FENTER();
+       MMPLAYER_RETURN_IF_FAIL(player);
+
+       attrs = MMPLAYER_GET_ATTRS(player);
+       if (!attrs) {
+               LOGE("failed to get content attribute");
+               return;
+       }
+
+       mm_attrs_get_string_by_name(attrs, "streaming_user_agent", &user_agent);
+
+       SECURE_LOGD("user_agent : %s", user_agent);
+
+       if (user_agent)
+               g_object_set(G_OBJECT(source), "user-agent", user_agent, NULL);
+
+       MMPLAYER_FLEAVE();
+}
+
 static void
 __mmplayer_gst_found_source(GObject *object, GObject *orig, GParamSpec *pspec, gpointer data)
 {
@@ -2868,16 +2859,7 @@ __mmplayer_gst_found_source(GObject *object, GObject *orig, GParamSpec *pspec, g
        if (MMPLAYER_IS_HTTP_STREAMING(player)) {
                __mmplayer_http_src_setup(source, data);
        } else if (MMPLAYER_IS_RTSP_STREAMING(player)) {
-               gchar *user_agent = NULL;
-
-               /* get attribute */
-               mm_attrs_get_string_by_name(player->attrs, "streaming_user_agent", &user_agent);
-
-               SECURE_LOGD("user_agent : %s", user_agent);
-
-               /* setting property to streaming source */
-               if (user_agent)
-                       g_object_set(G_OBJECT(source), "user-agent", user_agent, NULL);
+               __mmplayer_rtsp_src_setup(source, data);
        } else if (MMPLAYER_IS_SMOOTH_STREAMING(player)) {
                g_object_set(G_OBJECT(source), "timeout", DEFAULT_HTTP_TIMEOUT, NULL);
        } else if (player->profile.uri_type == MM_PLAYER_URI_TYPE_MEM) {
@@ -2885,10 +2867,12 @@ __mmplayer_gst_found_source(GObject *object, GObject *orig, GParamSpec *pspec, g
                        "size", (gint64)player->profile.input_mem.len, "blocksize", 20480, NULL);
 
                _mmplayer_add_signal_connection(player, G_OBJECT(source), MM_PLAYER_SIGNAL_TYPE_OTHERS, "seek-data",
-                                                                               G_CALLBACK(__mmplayer_gst_appsrc_seek_data_mem), (gpointer)&player->profile.input_mem);
+                                               G_CALLBACK(__mmplayer_gst_appsrc_seek_data_mem), (gpointer)&player->profile.input_mem);
                _mmplayer_add_signal_connection(player, G_OBJECT(source), MM_PLAYER_SIGNAL_TYPE_OTHERS, "need-data",
-                                                                               G_CALLBACK(__mmplayer_gst_appsrc_feed_data_mem), (gpointer)&player->profile.input_mem);
+                                               G_CALLBACK(__mmplayer_gst_appsrc_feed_data_mem), (gpointer)&player->profile.input_mem);
        }
+       gst_object_unref (source);
+
        MMPLAYER_FLEAVE();
 }
 
@@ -2896,40 +2880,65 @@ static gint
 __mmplayer_gst_select_stream (GstElement * uridecodebin, GstStreamCollection * collection,
     GstStream * stream, gpointer data)
 {
-       gint ret = 0; /* 1: select, 0: skip, -1: depends on decodebin */
+#define RET_SELECT 1
+#define RET_SKIP 0
+#define RET_DEPENDS_ON_DECODEBIN -1
+
        GstStreamType stype = gst_stream_get_stream_type(stream);
        mmplayer_t *player = (mmplayer_t *)data;
        mmplayer_track_type_e type = MM_PLAYER_TRACK_TYPE_MAX;
-       GstCaps *caps = gst_stream_get_caps(stream);
-       gchar *caps_str = NULL;
+       g_autoptr(GstCaps) caps = gst_stream_get_caps(stream);
+       g_autofree gchar *caps_str = NULL;
+       GstStructure *caps_structure = NULL;
+       int stream_index = INVALID_TRACK_INDEX;
+       int ret = MM_ERROR_NONE;
 
        LOGD("Stream type %s flags 0x%x",
                        gst_stream_type_get_name(stype),
                        gst_stream_get_stream_flags(stream));
        LOGD("  ID: %s", gst_stream_get_stream_id(stream));
 
+       type = __mmplayer_convert_gst_stream_type_to_track_type(stype);
+
        if (caps) {
                caps_str = gst_caps_to_string(caps);
+               caps_structure = gst_caps_get_structure(caps, 0);
+               const gchar *mime = gst_structure_get_name(caps_structure);
+
                LOGD("  caps: %s", caps_str);
+
+               for (int idx = 0; player->ini.unsupported_codec_keyword[idx][0] != '\0'; idx++) {
+                       if (caps_str && strstr(caps_str, player->ini.unsupported_codec_keyword[idx])) {
+                               LOGW("skip [%s] by unsupported codec keyword [%s]",
+                                               mime, player->ini.unsupported_codec_keyword[idx]);
+
+                               _mmplayer_update_not_supported_codec_info(player, NULL, mime);
+                               return RET_SKIP;
+                       }
+               }
+       } else if (type == MM_PLAYER_TRACK_TYPE_AUDIO || type == MM_PLAYER_TRACK_TYPE_VIDEO) {
+               if (MMPLAYER_IS_HTTP_LIVE_STREAMING(player) || MMPLAYER_IS_DASH_STREAMING(player)) {
+                       LOGD("No caps info, depends on decodebin");
+                       _mmplayer_track_update_stream(player, type, stream);
+                       return RET_DEPENDS_ON_DECODEBIN;
+               }
+
+               LOGD("No caps info, skip it");
+               return RET_SKIP;
        }
 
        switch (stype) {
        case GST_STREAM_TYPE_AUDIO:
        {
-               GstStructure *caps_structure = NULL;
-               gint samplerate = 0;
-               gint channels = 0;
-
-               type = MM_PLAYER_TRACK_TYPE_AUDIO;
+               if (caps_structure) {
+                       gint samplerate = 0;
+                       gint channels = 0;
 
-               if (caps) {
-                       caps_structure = gst_caps_get_structure(caps, 0);
                        gst_structure_get_int(caps_structure, "rate", &samplerate);
                        gst_structure_get_int(caps_structure, "channels", &channels);
-
-                       if (channels > 0 && samplerate == 0) {
+                       if (samplerate == 0 && channels > 0) {
                                LOGW("Skip corrupted audio stream");
-                               goto EXIT;
+                               return RET_SKIP;
                        }
 
                        if (g_strrstr(caps_str, "mobile-xmf"))
@@ -2940,29 +2949,28 @@ __mmplayer_gst_select_stream (GstElement * uridecodebin, GstStreamCollection * c
        }
        case GST_STREAM_TYPE_VIDEO:
        {
-               GstStructure *caps_structure = NULL;
-               gint stype = 0;
-               gint width = 0;
-
-               type = MM_PLAYER_TRACK_TYPE_VIDEO;
-
-               /* do not support multi track video */
-               if (player->track[MM_PLAYER_TRACK_TYPE_VIDEO].total_track_num >= 1)
-                       goto EXIT;
+               if (player->track[MM_PLAYER_TRACK_TYPE_VIDEO].total_track_num >= 1) {
+                       LOGD("do not support muti track video");
+                       break;
+               }
 
-               mm_attrs_get_int_by_name(player->attrs, "display_surface_type", &stype);
+               // FIXME: it cause block during preparing
+               if ((!MMPLAYER_IS_HTTP_LIVE_STREAMING(player)) && (!MMPLAYER_IS_DASH_STREAMING(player))) {
+                       gint stype = 0;
 
-               /* don't make video because of not required */
-               if ((stype == MM_DISPLAY_SURFACE_NULL) &&
-                       (!player->set_mode.video_export)) {
-                       LOGD("no need video decoding, skip video stream");
-                       goto EXIT;
+                       mm_attrs_get_int_by_name(player->attrs, "display_surface_type", &stype);
+                       /* don't make video because of not required */
+                       if ((stype == MM_DISPLAY_SURFACE_NULL) &&
+                               (!player->set_mode.video_export)) {
+                               LOGD("no need video decoding, skip video stream");
+                               return RET_SKIP;
+                       }
                }
 
-               if (caps) {
-                       caps_structure = gst_caps_get_structure(caps, 0);
-                       gst_structure_get_int(caps_structure, "width", &width);
+               if (caps_structure) {
+                       gint width = 0;
 
+                       gst_structure_get_int(caps_structure, "width", &width);
                        if (width != 0) {
                                if (player->v_stream_caps) {
                                        gst_caps_unref(player->v_stream_caps);
@@ -2976,29 +2984,32 @@ __mmplayer_gst_select_stream (GstElement * uridecodebin, GstStreamCollection * c
                break;
        }
        case GST_STREAM_TYPE_TEXT:
-               type = MM_PLAYER_TRACK_TYPE_TEXT;
                break;
        default:
                LOGW("Skip not supported stream type");
-               goto EXIT;
+               return RET_SKIP;
        }
 
        _mmplayer_track_update_stream(player, type, stream);
 
-       if (player->track[type].active_track_index == (player->track[type].total_track_num - 1)) {
-               LOGD("select this stream, active idx : %d", player->track[type].active_track_index);
+       ret = _mmplayer_get_track_index(player, type, stream, &stream_index);
+
+       if ((player->track[type].active_track_index == INVALID_TRACK_INDEX) &&
+               (ret == MM_ERROR_NONE)) {
+               player->track[type].active_track_index = stream_index;
+               LOGD("select this stream, active track idx : %d", player->track[type].active_track_index);
                if (type == MM_PLAYER_TRACK_TYPE_AUDIO)
                        _mmplayer_set_audio_attrs(player, caps);
-               ret = 1;
+               return RET_SELECT;
        }
 
-EXIT:
-       g_free(caps_str);
-       if (caps)
-               gst_caps_unref(caps);
+       if (player->track[type].active_track_index == stream_index) {
+               LOGD("already activate track idx : %d", player->track[type].active_track_index);
+               return RET_SELECT;
+       }
 
-       LOGD("ret %d", ret);
-       return ret;
+       LOGD("Skip stream");
+       return RET_SKIP;
 }
 
 static gboolean
@@ -3029,138 +3040,147 @@ __mmplayer_gst_decode_request_resource(GstElement * uridecodebin, GstStreamColle
        return TRUE;
 }
 
-static void
-__mmplayer_gst_deep_element_added(GstElement *bin, GstBin *child, GstElement *element, gpointer data)
+static GstElement *
+__mmplayer_gst_find_child_element(GstBin *bin, const gchar *element_name)
 {
-       gchar *factory_name = NULL;
-       mmplayer_t *player = (mmplayer_t *)data;
-       mmplayer_gst_element_t *mainbin = NULL;
+       GstIterator *iter = NULL;
+       GValue item = {0, };
+       GstElement *ch_element = NULL;
+       GstElementFactory *ch_factory = NULL;
 
        MMPLAYER_FENTER();
-       MMPLAYER_RETURN_IF_FAIL(player && player->pipeline && player->pipeline->mainbin);
+       MMPLAYER_RETURN_VAL_IF_FAIL(bin && element_name, NULL);
 
-       factory_name = GST_OBJECT_NAME(gst_element_get_factory(element));
-       mainbin = player->pipeline->mainbin;
+       iter = gst_bin_iterate_recurse(bin);
+       MMPLAYER_RETURN_VAL_IF_FAIL(iter, NULL);
 
-       LOGD("%s > %s > %s : %s", GST_ELEMENT_NAME(bin), GST_ELEMENT_NAME(child),
-               factory_name, GST_ELEMENT_NAME(element));
+       while (gst_iterator_next(iter, &item) == GST_ITERATOR_OK) {
+               ch_element = g_value_get_object(&item);
+               ch_factory = gst_element_get_factory(ch_element);
+               LOGD("children factory %s", GST_OBJECT_NAME(ch_factory));
+               if (g_strrstr(GST_OBJECT_NAME(ch_factory), element_name)) {
+                       LOGD("Find %s element", element_name);
+                       break;
+               }
+               ch_element = NULL;
+               g_value_reset(&item);
+       }
+       g_value_unset(&item);
+       gst_iterator_free(iter);
 
-       /* keep the first typefind reference only */
-       if (!mainbin[MMPLAYER_M_TYPEFIND].gst && g_strrstr(factory_name, "typefind")) {  // FIXME : not required for local playback+
-               mainbin[MMPLAYER_M_TYPEFIND].id = MMPLAYER_M_TYPEFIND;
-               mainbin[MMPLAYER_M_TYPEFIND].gst = element;
+       MMPLAYER_FLEAVE();
+       return ch_element;
+}
 
-               _mmplayer_add_signal_connection(player, G_OBJECT(element),
-                       MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "have-type", G_CALLBACK(_mmplayer_typefind_have_type), (gpointer)player);
-               LOGD("typefind reference is added");
-               return;
-       }
+static void __mmplayer_parsebin_setup(GstBin *bin, gpointer data)
+{
+       mmplayer_t *player = (mmplayer_t *)data;
 
-       if ((MMPLAYER_IS_STREAMING(player)) && (!MMPLAYER_IS_RTSP_STREAMING(player))) {
-               /* update queue2 setting */
-               if (g_strrstr(factory_name, "queue2") && (!mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst)) {
-                       gint64 dur_bytes = 0L;
-                       muxed_buffer_type_e type = MUXED_BUFFER_TYPE_MEM_QUEUE;
+       g_object_set(G_OBJECT(bin), "message-forward", TRUE, NULL);
 
-                       mainbin[MMPLAYER_M_MUXED_S_BUFFER].id = MMPLAYER_M_MUXED_S_BUFFER;
-                       mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst = element;
+       _mmplayer_add_signal_connection(player, G_OBJECT(bin),
+       MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "unknown-type",
+                       G_CALLBACK(_mmplayer_gst_decode_unknown_type), (gpointer)player);
 
-                       if (!gst_element_query_duration(mainbin[MMPLAYER_M_SRC].gst, GST_FORMAT_BYTES, &dur_bytes))
-                               LOGW("failed to get duration from source %s", GST_ELEMENT_NAME(mainbin[MMPLAYER_M_SRC].gst));
+       _mmplayer_add_signal_connection(player, G_OBJECT(bin),
+       MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "autoplug-select",
+                       G_CALLBACK(_mmplayer_gst_decode_autoplug_select), (gpointer)player);
+}
 
-                       LOGD("type %s, dur_bytes = %"G_GINT64_FORMAT, player->type, dur_bytes);
-                       /* NOTE : in case of ts streaming, player could not get the correct duration info *
-                        *                skip the pull mode(file or ring buffering) setting. */
-                       if (dur_bytes > 0) {
-                               if ((!g_strrstr(player->type, "video/mpegts")) && (!g_strrstr(player->type, "application/x-hls"))) {
-                                       type = MUXED_BUFFER_TYPE_MEM_RING_BUFFER;
-                                       player->streamer->ring_buffer_size = player->ini.http_ring_buffer_size;
-                               }
-                       } else {
-                               dur_bytes = 0;
-                       }
+static void __mmplayer_decodebin3_setup(GstBin *bin, gpointer data)
+{
+       mmplayer_t *player = (mmplayer_t *)data;
+       int video_codec_type = 0;
+       int audio_codec_type = 0;
 
-                       _mm_player_streaming_set_queue2(player->streamer,
-                                                                                       element,
-                                                                                       FALSE,
-                                                                                       type,
-                                                                                       (guint64)dur_bytes); /* no meaning at the moment */
-                       return;
-               }
+       g_object_set(G_OBJECT(bin), "message-forward", TRUE, NULL);
 
-               /* update mq setting */
-               if (g_strrstr(factory_name, "parsebin") && (!mainbin[MMPLAYER_M_DEMUXED_S_BUFFER].gst)) {
-                       GstIterator *iter = NULL;
-                       GValue item = {0, };
-                       GstElement *ch_element = NULL;
-                       GstElementFactory *ch_factory = NULL;
-
-                       iter = gst_bin_iterate_recurse(child);
-                       if (iter != NULL) {
-                               while (gst_iterator_next(iter, &item) == GST_ITERATOR_OK) {
-                                       ch_element = g_value_get_object(&item);
-                                       ch_factory = gst_element_get_factory(ch_element);
-                                       LOGD("children factory %s", GST_OBJECT_NAME(ch_factory));
-                                       if (g_strrstr(GST_OBJECT_NAME(ch_factory), "multiqueue")) {
-                                               LOGD("get multiqueue");
-                                               player->pipeline->mainbin[MMPLAYER_M_DEMUXED_S_BUFFER].id = MMPLAYER_M_DEMUXED_S_BUFFER;
-                                               player->pipeline->mainbin[MMPLAYER_M_DEMUXED_S_BUFFER].gst = ch_element;
-
-                                               /* in case of multiqueue, max bytes size is defined with fixed value in mm_player_streaming.h */
-                                               _mm_player_streaming_set_multiqueue(player->streamer, ch_element);
-                                               g_value_reset(&item);
-                                               break;
-                                       }
-                                       g_value_reset(&item);
-                               }
-                               gst_iterator_free(iter);
-                       }
-               }
-       }
+       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);
 
-       if (g_strrstr(factory_name, "parsebin")) {
-               int video_codec_type = 0;
-               int audio_codec_type = 0;
+       LOGD("set codec type v(%d) a(%d)", video_codec_type, audio_codec_type);
 
-               g_object_set(G_OBJECT(child), "message-forward", TRUE, NULL);
-               g_object_set(G_OBJECT(element), "message-forward", TRUE, NULL);
+       if (video_codec_type == MM_PLAYER_CODEC_TYPE_SW)
+               g_object_set(G_OBJECT(bin), "force-sw-decoders-for-video", TRUE, NULL);
+       if (audio_codec_type == MM_PLAYER_CODEC_TYPE_SW)
+               g_object_set(G_OBJECT(bin), "force-sw-decoders-for-audio", TRUE, 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);
+       _mmplayer_add_signal_connection(player, G_OBJECT(bin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG,
+                       "request-resource", G_CALLBACK(__mmplayer_gst_decode_request_resource), (gpointer)player);
+}
 
-               /* CAUTION: if there is hw decoder, the rank value has to be higher than sw decoder
-                  and codec default type in ini has to be hw.
-                */
-               if (video_codec_type == MM_PLAYER_CODEC_TYPE_SW)
-                       g_object_set(G_OBJECT(child), "force-sw-decoder-for-video", TRUE, NULL);
-               if (audio_codec_type == MM_PLAYER_CODEC_TYPE_SW)
-                       g_object_set(G_OBJECT(child), "force-sw-decoder-for-audio", TRUE, NULL);
+static void
+__mmplayer_gst_deep_element_added(GstElement *bin, GstBin *child, GstElement *element, gpointer data)
+{
+       gchar *factory_name = NULL;
+       mmplayer_t *player = (mmplayer_t *)data;
 
-               mainbin[MMPLAYER_M_AUTOPLUG_PARSEBIN].id = MMPLAYER_M_AUTOPLUG_PARSEBIN;
-               mainbin[MMPLAYER_M_AUTOPLUG_PARSEBIN].gst = element;
-               _mmplayer_add_signal_connection(player, G_OBJECT(element),
-                       MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "unknown-type", G_CALLBACK(_mmplayer_gst_decode_unknown_type), (gpointer)player);
+       MMPLAYER_FENTER();
+       MMPLAYER_RETURN_IF_FAIL(player && player->pipeline && player->pipeline->mainbin);
 
-               _mmplayer_add_signal_connection(player, G_OBJECT(element),
-                       MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "autoplug-continue", G_CALLBACK(_mmplayer_gst_decode_autoplug_continue), (gpointer)player);
+       factory_name = GST_OBJECT_NAME(gst_element_get_factory(element));
 
-               _mmplayer_add_signal_connection(player, G_OBJECT(element),
-                       MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "autoplug-select", G_CALLBACK(_mmplayer_gst_decode_autoplug_select), (gpointer)player);
+       LOGD("child: %s, elem: %s (%s)", GST_ELEMENT_NAME(child), factory_name, GST_ELEMENT_NAME(element));
 
-               _mmplayer_add_signal_connection(player, G_OBJECT(child),
-                       MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "request-resource", G_CALLBACK(__mmplayer_gst_decode_request_resource), (gpointer)player);
+       if (g_strrstr(factory_name, "urisourcebin")) {
+               GstElement *dbin3 = __mmplayer_gst_find_child_element(child, "decodebin3");
+               if (dbin3) {
+                       GstElement *mq = __mmplayer_gst_find_child_element(child, "multiqueue");
+                       if (mq)
+                               g_object_set(G_OBJECT(mq), "use-interleave", FALSE, NULL);
 
+                       __mmplayer_decodebin3_setup(GST_BIN(dbin3), data);
+               } else {
+                       LOGW("failed to find decodebin3");
+               }
+       } else if (g_strrstr(factory_name, "parsebin")) {
+               g_object_set(G_OBJECT(child), "message-forward", TRUE, NULL); /* urisourcebin */
+               __mmplayer_parsebin_setup(GST_BIN(element), data);
        } else {
-               _mmplayer_gst_element_added((GstElement *)child, element, data);
+               _mmplayer_gst_element_added(child, element, data);
        }
-       return;
+}
+
+static void
+__mmplayer_delete_signal_connection(mmplayer_t *player, GstElement *removed_element)
+{
+       MMPLAYER_FENTER();
+
+       MMPLAYER_RETURN_IF_FAIL(player);
+       MMPLAYER_RETURN_IF_FAIL(removed_element);
+
+       LOGD("delete signal on %s", GST_ELEMENT_NAME(removed_element));
+
+       for (int type = MM_PLAYER_SIGNAL_TYPE_AUTOPLUG; type < MM_PLAYER_SIGNAL_TYPE_ALL; type++) {
+               GList *node = player->signals[type];
+               while (node) {
+                       GList *next_node = node->next;
+                       mmplayer_signal_item_t *item = node->data;
+                       if (item && item->obj == G_OBJECT(removed_element)) {
+                               player->signals[type] = g_list_delete_link(player->signals[type], node);
+                               MMPLAYER_FREEIF(item);
+                       }
+                       node = next_node;
+               }
+       }
+
+       MMPLAYER_FLEAVE();
 }
 
 void
 __mmplayer_gst_deep_element_removed(GstElement *bin, GstBin *child, GstElement *element, gpointer data)
 {
+       mmplayer_t *player = (mmplayer_t *)data;
+
+       MMPLAYER_FENTER();
+
+       MMPLAYER_RETURN_IF_FAIL(player);
+
        LOGD("%s > %s > %s", GST_ELEMENT_NAME(bin), GST_ELEMENT_NAME(child), GST_ELEMENT_NAME(element));
-       return;
+
+       __mmplayer_delete_signal_connection(player, element);
+
+       MMPLAYER_FLEAVE();
 }
 
 static GstElement *
@@ -3183,7 +3203,8 @@ __mmplayer_gst_make_uridecodebin(mmplayer_t *player)
        /* setting property to streaming source */
        g_object_set(G_OBJECT(uridecodebin3), "uri", player->profile.uri,
                        "message-forward", TRUE,
-                       "buffer-size", DEFAULT_BUFFER_SIZE_BYTES, NULL);
+                       "buffer-size", DEFAULT_BUFFER_SIZE_BYTES,
+                       "use-buffering", TRUE, NULL);
 
        _mmplayer_add_signal_connection(player, G_OBJECT(uridecodebin3),
                MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "deep-notify::source", G_CALLBACK(__mmplayer_gst_found_source), (gpointer)player);
@@ -3200,10 +3221,8 @@ __mmplayer_gst_make_uridecodebin(mmplayer_t *player)
        _mmplayer_add_signal_connection(player, G_OBJECT(uridecodebin3),
                MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "select-stream", G_CALLBACK(__mmplayer_gst_select_stream), (gpointer)player);
 
-/* FIXME: need to be added for gapless playback
-       _mmplayer_add_signal_connection(player, G_OBJECT(element),
-               MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "about-to-finish", G_CALLBACK(_mmplayer_gst_decode_drained), (gpointer)player);
-*/
+       _mmplayer_add_signal_connection(player, G_OBJECT(uridecodebin3),
+               MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "about-to-finish", G_CALLBACK(_mmplayer_gst_about_to_finish), (gpointer)player);
 
        _mmplayer_add_signal_connection(player, G_OBJECT(uridecodebin3),
                MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "deep-element-added", G_CALLBACK(__mmplayer_gst_deep_element_added), (gpointer)player);
@@ -3240,7 +3259,7 @@ __mmplayer_gst_make_http_src(mmplayer_t *player)
                return NULL;
        }
 
-       LOGD("using http streamming source [%s]", player->ini.httpsrc_element);
+       LOGD("using http streaming source [%s]", player->ini.httpsrc_element);
 
        element = gst_element_factory_make(player->ini.httpsrc_element, "http_streaming_source");
        if (!element) {
@@ -3364,9 +3383,10 @@ static gpointer __mmplayer_gst_bus_msg_thread(gpointer data)
 }
 
 static int
-__mmplayer_gst_check_duration(mmplayer_t *player, gint64 position)
+__mmplayer_gst_check_position(mmplayer_t *player, gint64 position)
 {
        gint64 dur_nsec = 0;
+       gint64 pos_nsec = 0;
 
        MMPLAYER_FENTER();
        MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
@@ -3375,7 +3395,7 @@ __mmplayer_gst_check_duration(mmplayer_t *player, gint64 position)
                return MM_ERROR_NONE;
 
        /* NOTE : duration cannot be zero except live streaming.
-        *              Since some element could have some timing problemn with quering duration, try again.
+        *              Since some element could have some timing problem with querying duration, try again.
         */
        if (player->duration == 0) {
                if (!gst_element_query_duration(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &dur_nsec)) {
@@ -3401,6 +3421,15 @@ __mmplayer_gst_check_duration(mmplayer_t *player, gint64 position)
                return MM_ERROR_INVALID_ARGUMENT;
        }
 
+       if (gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &pos_nsec)) {
+               if ((pos_nsec == player->duration) && /* current pos is end of stream  */
+                       ((position / GST_MSECOND) == (player->duration / GST_MSECOND))) {
+                       MMPLAYER_POST_MSG(player, MM_MESSAGE_SEEK_COMPLETED, NULL);
+                       player->seek_state = MMPLAYER_SEEK_NONE;
+                       return MM_ERROR_PLAYER_NO_OP;
+               }
+       }
+
        MMPLAYER_FLEAVE();
        return MM_ERROR_NONE;
 }
@@ -3513,7 +3542,7 @@ _mmplayer_gst_start(mmplayer_t *player)
 
                MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_PLAYING;
                if (__mmplayer_gst_pending_seek(player) != MM_ERROR_NONE)
-                               LOGW("failed to seek pending postion. starting from the begin of content");
+                               LOGW("failed to seek pending position. starting from the begin of content");
        }
 
        LOGD("current state before doing transition");
@@ -3562,7 +3591,7 @@ _mmplayer_gst_stop(mmplayer_t *player)
                return MM_ERROR_PLAYER_INTERNAL;
        }
 
-       /* Just set state to PAUESED and the rewind. it's usual player behavior. */
+       /* Just set state to PAUSED and the rewind. it's usual player behavior. */
        timeout = MMPLAYER_STATE_CHANGE_TIMEOUT(player);
 
        if ((!MMPLAYER_IS_STREAMING(player) && !MMPLAYER_IS_MS_BUFF_SRC(player)) ||
@@ -3677,7 +3706,7 @@ _mmplayer_gst_pause(mmplayer_t *player, gboolean async)
                                                /* Note : the streaming error from the streaming source is handled
                                                        *   using __mmplayer_handle_streaming_error.
                                                        */
-                                               __mmplayer_handle_streaming_error(player, msg);
+                                               __mmplayer_handle_streaming_error(player, msg, error);
 
                                        } else if (error) {
                                                LOGE("paring error posted from bus, domain : %s, code : %d", g_quark_to_string(error->domain), error->code);
@@ -3799,7 +3828,7 @@ _mmplayer_gst_send_event_to_sink(mmplayer_t *player, GstEvent *event)
                                LOGD("sending event[%s] to sink element [%s] success!",
                                        GST_EVENT_TYPE_NAME(event), GST_ELEMENT_NAME(sink));
 
-                               /* rtsp case, asyn_done is not called after seek during pause state */
+                               /* rtsp case, async_done is not called after seek during pause state */
                                if (MMPLAYER_IS_RTSP_STREAMING(player)) {
                                        if (GST_EVENT_TYPE(event) == GST_EVENT_SEEK) {
                                                if (MMPLAYER_TARGET_STATE(player) == MM_PLAYER_STATE_PAUSED) {
@@ -3827,7 +3856,7 @@ _mmplayer_gst_send_event_to_sink(mmplayer_t *player, GstEvent *event)
        }
 
        /* Note : Textbin is not linked to the video or audio bin.
-        * It needs to send the event to the text sink seperatelly.
+        * It needs to send the event to the text sink separately.
         */
        if (player->play_subtitle && player->pipeline) {
                GstElement *text_sink = GST_ELEMENT_CAST(player->pipeline->textbin[MMPLAYER_T_FAKE_SINK].gst);
@@ -3884,7 +3913,7 @@ _mmplayer_gst_set_position(mmplayer_t *player, gint64 position, gboolean interna
 {
        int ret = MM_ERROR_NONE;
        gint64 pos_nsec = 0;
-       gboolean accurated = FALSE;
+       gboolean accurate = FALSE;
        GstSeekFlags seek_flags = GST_SEEK_FLAG_FLUSH;
 
        MMPLAYER_FENTER();
@@ -3895,9 +3924,9 @@ _mmplayer_gst_set_position(mmplayer_t *player, gint64 position, gboolean interna
                && (MMPLAYER_CURRENT_STATE(player) != MM_PLAYER_STATE_PAUSED))
                goto PENDING;
 
-       ret = __mmplayer_gst_check_duration(player, position);
+       ret = __mmplayer_gst_check_position(player, position);
        if (ret != MM_ERROR_NONE) {
-               LOGE("failed to check duration 0x%X", ret);
+               LOGW("result of check position info 0x%X", ret);
                return (ret == MM_ERROR_PLAYER_NO_OP) ? MM_ERROR_NONE : ret;
        }
 
@@ -3942,8 +3971,8 @@ _mmplayer_gst_set_position(mmplayer_t *player, gint64 position, gboolean interna
                player->seek_state = MMPLAYER_SEEK_NONE;
                MMPLAYER_POST_MSG(player, MM_MESSAGE_SEEK_COMPLETED, NULL);
        } else {
-               mm_attrs_get_int_by_name(player->attrs, "accurate_seek", &accurated);
-               if (accurated)
+               mm_attrs_get_int_by_name(player->attrs, "accurate_seek", &accurate);
+               if (accurate)
                        seek_flags |= GST_SEEK_FLAG_ACCURATE;
                else
                        seek_flags |= GST_SEEK_FLAG_KEY_UNIT;
@@ -3961,7 +3990,7 @@ _mmplayer_gst_set_position(mmplayer_t *player, gint64 position, gboolean interna
         */
        player->last_position = position;
 
-       /* MSL should guarante playback rate when seek is selected during trick play of fast forward. */
+       /* MSL should guarantee playback rate when seek is selected during trick play of fast forward. */
        if (player->playback_rate > 1.0)
                _mmplayer_set_playspeed((MMHandleType)player, player->playback_rate, FALSE);
 
@@ -4012,7 +4041,7 @@ _mmplayer_gst_get_position(mmplayer_t *player, gint64 *position)
 
        /* NOTE : get last point to overcome some bad operation of some elements
         *(returning zero when getting current position in paused state
-        * and when failed to get postion during seeking
+        * and when failed to get position during seeking
         */
        if ((current_state == MM_PLAYER_STATE_PAUSED) || (!ret)) {
                LOGD("pos_nsec = %"GST_TIME_FORMAT" and ret = %d and state = %d", GST_TIME_ARGS(pos_nsec), ret, current_state);
@@ -4147,7 +4176,7 @@ _mmplayer_gst_get_buffer_position(mmplayer_t *player, int *start_pos, int *end_p
                                g_object_get(G_OBJECT(mainbin[MMPLAYER_M_DEMUXED_S_BUFFER].gst),
                                        "curr-size-bytes", &curr_size_bytes, NULL);
                                LOGD("curr_size_bytes of multiqueue = %d", curr_size_bytes);
-                               buffered_total += curr_size_bytes;
+                               buffered_total += (gint64)curr_size_bytes;
                        }
 
                        if (avg_byterate > 0)
@@ -4268,7 +4297,6 @@ _mmplayer_gst_build_pipeline_with_src(mmplayer_t *player)
                goto ERROR;
        }
 
-       /* FIXME: required ?*/
        /* create fakesink element for keeping the pipeline state PAUSED. if needed */
        mainbin[MMPLAYER_M_SRC_FAKESINK].id = MMPLAYER_M_SRC_FAKESINK;
        mainbin[MMPLAYER_M_SRC_FAKESINK].gst = gst_element_factory_make("fakesink", "state-holder");
@@ -4539,6 +4567,7 @@ _mmplayer_gst_add_bus_watch(mmplayer_t *player)
 void
 _mmplayer_activate_next_source(mmplayer_t *player, GstState target)
 {
+       int ret = MM_ERROR_NONE;
        mmplayer_gst_element_t *mainbin = NULL;
        MMMessageParamType msg_param = {0,};
        GstElement *element = NULL;
@@ -4577,6 +4606,18 @@ _mmplayer_activate_next_source(mmplayer_t *player, GstState target)
                goto ERROR;
        }
 
+       if (!MMPLAYER_USE_DECODEBIN(player)) {
+               ret = _mmplayer_gst_build_pipeline_with_src(player);
+               if (ret != MM_ERROR_NONE)
+                       goto ERROR;
+
+               if (gst_element_set_state(mainbin[MMPLAYER_M_AUTOPLUG].gst, target) == GST_STATE_CHANGE_FAILURE) {
+                       LOGE("Failed to change state of uridecodebin3 element");
+                       goto ERROR;
+               }
+               goto DONE;
+       }
+
        element = _mmplayer_gst_create_source(player);
        if (!element) {
                LOGE("no source element was created");
@@ -4618,7 +4659,7 @@ _mmplayer_activate_next_source(mmplayer_t *player, GstState target)
        }
 
        if (gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), element) == FALSE) {
-               LOGE("failed to add sinkbin to pipeline");
+               LOGE("failed to add %s to pipeline", GST_ELEMENT_NAME(element));
                gst_object_unref(GST_OBJECT(element));
                element = NULL;
                goto ERROR;
@@ -4649,6 +4690,7 @@ _mmplayer_activate_next_source(mmplayer_t *player, GstState target)
                goto ERROR;
        }
 
+DONE:
        player->gapless.stream_changed = TRUE;
        player->gapless.running = TRUE;
        MMPLAYER_FLEAVE();