[0.6.264] Delete video sink when player set audio only
[platform/core/multimedia/libmm-player.git] / src / mm_player_priv.c
index 8396f5f..6f88332 100644 (file)
@@ -196,6 +196,7 @@ static gboolean __mmplayer_swcodec_set_bo(mmplayer_t *player, mmplayer_video_dec
 
 static void __mmplayer_set_pause_state(mmplayer_t *player);
 static void __mmplayer_set_playing_state(mmplayer_t *player);
+static int __mmplayer_switch_stream(mmplayer_t *player, mmplayer_track_type_e type, int index);
 /*===========================================================================================
 |                                                                                                                                                                                      |
 |  FUNCTION DEFINITIONS                                                                                                                                                |
@@ -801,10 +802,14 @@ _mmplayer_bus_watcher_remove(MMHandleType hplayer)
                __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);
+               while (player->bus_watcher > 0) {
+                       if (!MMPLAYER_BUS_WATCHER_WAIT_UNTIL(player, end_time)) {
+                               LOGW("MMPLAYER_BUS_WATCHER_WAIT_UNTIL() timeout has passed - bus_watcher (%d)",
+                                               player->bus_watcher);
+                               break;
+                       }
+               }
                MMPLAYER_BUS_WATCHER_UNLOCK(player);
-
                g_mutex_clear(&player->bus_watcher_mutex);
                g_cond_clear(&player->bus_watcher_cond);
        }
@@ -1139,13 +1144,13 @@ __mmplayer_gst_make_fakesink(mmplayer_t *player, GstPad *pad, const gchar *name)
        fakesink = gst_element_factory_make("fakesink", NULL);
        if (fakesink == NULL) {
                LOGE("failed to create fakesink");
-               goto EXIT;
+               return;
        }
 
-       /* store it as it's sink element */
-       __mmplayer_add_sink(player, fakesink, FALSE);
-
-       gst_bin_add(GST_BIN(pipeline), fakesink);
+       if (!gst_bin_add(GST_BIN(pipeline), fakesink)) {
+               LOGE("failed to add fakesink to pipeline");
+               goto ERROR;
+       }
 
        /* link */
        sinkpad = gst_element_get_static_pad(fakesink, "sink");
@@ -1154,8 +1159,7 @@ __mmplayer_gst_make_fakesink(mmplayer_t *player, GstPad *pad, const gchar *name)
 
        if (gst_pad_link(pad, sinkpad) != GST_PAD_LINK_OK) {
                LOGE("failed to link fakesink");
-               gst_object_unref(GST_OBJECT(fakesink));
-               goto EXIT;
+               goto ERROR;
        }
 
        if (strstr(name, "video")) {
@@ -1170,12 +1174,28 @@ __mmplayer_gst_make_fakesink(mmplayer_t *player, GstPad *pad, const gchar *name)
        g_object_set(G_OBJECT(fakesink), "sync", TRUE, NULL);
        gst_element_set_state(fakesink, GST_STATE_PAUSED);
 
-EXIT:
+       /* store it as it's sink element */
+       __mmplayer_add_sink(player, fakesink, FALSE);
+
        if (sinkpad)
                gst_object_unref(GST_OBJECT(sinkpad));
 
        MMPLAYER_FLEAVE();
        return;
+
+ERROR:
+
+       if (sinkpad)
+               gst_object_unref(GST_OBJECT(sinkpad));
+
+       if (fakesink) {
+               gst_element_set_state(fakesink, GST_STATE_NULL);
+
+               if (!gst_bin_remove(GST_BIN(pipeline), fakesink))
+                       gst_object_unref(GST_OBJECT(fakesink));
+       }
+
+       return;
 }
 
 static GstElement *
@@ -1193,16 +1213,21 @@ __mmplayer_gst_make_concat(mmplayer_t *player, main_element_id_e elem_idx)
                return NULL;
        }
 
+       gst_element_set_state(concat, GST_STATE_PAUSED);
+
+       pipeline = player->pipeline->mainbin[MMPLAYER_M_PIPE].gst;
+       if (!gst_bin_add(GST_BIN(pipeline), concat)) {
+               LOGE("failed to add concat to pipeline");
+               gst_element_set_state(concat, GST_STATE_NULL);
+               gst_object_unref(GST_OBJECT(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;
 }
@@ -1224,11 +1249,6 @@ __mmplayer_gst_make_selector(mmplayer_t *player, main_element_id_e elem_idx, mmp
        }
        g_object_set(selector, "sync-streams", TRUE, NULL);
 
-       player->pipeline->mainbin[elem_idx].id = elem_idx;
-       player->pipeline->mainbin[elem_idx].gst = selector;
-
-       /* 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));
@@ -1240,10 +1260,29 @@ __mmplayer_gst_make_selector(mmplayer_t *player, main_element_id_e elem_idx, mmp
        gst_element_set_state(selector, GST_STATE_PAUSED);
 
        pipeline = player->pipeline->mainbin[MMPLAYER_M_PIPE].gst;
-       gst_bin_add(GST_BIN(pipeline), selector);
+       if (!gst_bin_add(GST_BIN(pipeline), selector)) {
+               LOGE("failed to add selector to pipeline");
+
+               if (player->track[stream_type].block_id != 0)
+                 gst_pad_remove_probe (srcpad, player->track[stream_type].block_id);
+               player->track[stream_type].block_id = 0;
+
+               if (player->track[stream_type].event_probe_id != 0)
+                 gst_pad_remove_probe (srcpad, player->track[stream_type].event_probe_id);
+               player->track[stream_type].event_probe_id = 0;
+
+               gst_object_unref(GST_OBJECT(srcpad));
+
+               gst_element_set_state(selector, GST_STATE_NULL);
+               gst_object_unref(GST_OBJECT(selector));
+               return NULL;
+       }
 
        gst_object_unref(GST_OBJECT(srcpad));
 
+       player->pipeline->mainbin[elem_idx].id = elem_idx;
+       player->pipeline->mainbin[elem_idx].gst = selector;
+
        MMPLAYER_FLEAVE();
        return selector;
 }
@@ -1410,6 +1449,7 @@ ERROR:
                sinkpad = NULL;
        }
 
+       MMPLAYER_GENERATE_DOT_IF_ENABLED(player, "pipeline-pad-added");
        return;
 }
 
@@ -1465,10 +1505,10 @@ __mmplayer_set_decode_track_info(mmplayer_t *player, mmplayer_track_type_e type)
 
        /* change track to active pad */
        active_index = player->track[type].active_track_index;
-       if ((active_index != DEFAULT_TRACK) &&
+       if ((active_index != DEFAULT_TRACK_INDEX) &&
                (__mmplayer_change_selector_pad(player, type, active_index) != MM_ERROR_NONE)) {
                LOGW("failed to change %d type track to %d", type, active_index);
-               player->track[type].active_track_index = DEFAULT_TRACK;
+               player->track[type].active_track_index = DEFAULT_TRACK_INDEX;
                return;
        }
 
@@ -1760,7 +1800,7 @@ __mmplayer_gst_create_sink_bin(GstElement *elem, GstPad *pad, GstCaps *ref_caps,
                        mm_attrs_get_int_by_name(player->attrs, "display_surface_type", &surface_type);
                        LOGD("display_surface_type (%d)", surface_type);
 
-                       if ((surface_type == MM_DISPLAY_SURFACE_OVERLAY) &&
+                       if ((surface_type == MM_DISPLAY_SURFACE_OVERLAY || surface_type == MM_DISPLAY_SURFACE_OVERLAY_SYNC_UI) &&
                                (_mmplayer_acquire_hw_resource(player, MMPLAYER_RESOURCE_TYPE_VIDEO_OVERLAY) != MM_ERROR_NONE)) {
                                LOGE("failed to acquire video overlay resource");
                                goto ERROR;
@@ -1977,7 +2017,8 @@ static void __mmplayer_video_param_set_display_visible(mmplayer_t *player)
        MMPLAYER_FENTER();
 
        /* check video sinkbin is created */
-       if (!_mmplayer_is_videosink_ready(player, MM_DISPLAY_SURFACE_OVERLAY))
+       if (!(_mmplayer_is_videosink_ready(player, MM_DISPLAY_SURFACE_OVERLAY) ||
+               _mmplayer_is_videosink_ready(player, MM_DISPLAY_SURFACE_OVERLAY_SYNC_UI)))
                return;
 
        attrs = MMPLAYER_GET_ATTRS(player);
@@ -2065,6 +2106,28 @@ static void __mmplayer_video_param_set_roi_area(mmplayer_t *player)
                win_roi_x, win_roi_y, win_roi_width, win_roi_height);
 }
 
+static void __mmplayer_video_param_set_display_overlay_sync_ui(mmplayer_t *player)
+{
+       MMHandleType attrs = 0;
+       gchar *handle = NULL;
+
+       /* check video sinkbin is created */
+       if (!_mmplayer_is_videosink_ready(player, MM_DISPLAY_SURFACE_OVERLAY_SYNC_UI))
+               return;
+
+       attrs = MMPLAYER_GET_ATTRS(player);
+       MMPLAYER_RETURN_IF_FAIL(attrs);
+
+       /* common case if using overlay surface */
+       mm_attrs_get_string_by_name(attrs, "exported_shell_handle", &handle);
+       MMPLAYER_RETURN_IF_FAIL(handle);
+
+       gst_video_overlay_set_wl_window_exported_shell_handle(
+                       GST_VIDEO_OVERLAY(player->pipeline->videobin[MMPLAYER_V_SINK].gst),
+                       handle);
+       LOGD("set video param: exported_shell_handle (%s)", handle);
+}
+
 static void __mmplayer_video_param_set_display_overlay(mmplayer_t *player)
 {
        MMHandleType attrs = 0;
@@ -2092,14 +2155,24 @@ int
 _mmplayer_update_video_overlay_param(mmplayer_t *player, const char *param_name)
 {
        gboolean update_all_param = FALSE;
+       int curr_type = MM_DISPLAY_SURFACE_NUM;
 
        MMPLAYER_FENTER();
 
-       if (!_mmplayer_is_videosink_ready(player, MM_DISPLAY_SURFACE_OVERLAY)) {
+       if (!player || !player->pipeline || !player->pipeline->mainbin || !player->pipeline->videobin ||
+               !player->pipeline->videobin[MMPLAYER_V_BIN].gst ||
+               !player->pipeline->videobin[MMPLAYER_V_SINK].gst) {
                LOGW("videosink is not ready yet");
                return MM_ERROR_PLAYER_NOT_INITIALIZED;
        }
 
+       mm_attrs_get_int_by_name(player->attrs, "display_surface_type", &curr_type);
+
+       if (curr_type != MM_DISPLAY_SURFACE_OVERLAY && curr_type != MM_DISPLAY_SURFACE_OVERLAY_SYNC_UI) {
+               LOGE("current type(%d) is wrong", curr_type);
+               return MM_ERROR_PLAYER_INTERNAL;
+       }
+
        if (strcmp(player->ini.videosink_element_overlay, "tizenwlsink")) {
                LOGE("invalid videosink [%s]", player->ini.videosink_element_overlay);
                return MM_ERROR_PLAYER_INTERNAL;
@@ -2109,6 +2182,11 @@ _mmplayer_update_video_overlay_param(mmplayer_t *player, const char *param_name)
        if (!g_strcmp0(param_name, "update_all_param"))
                update_all_param = TRUE;
 
+       if (curr_type == MM_DISPLAY_SURFACE_OVERLAY_SYNC_UI) {
+               __mmplayer_video_param_set_display_overlay_sync_ui(player);
+               MMPLAYER_FLEAVE();
+               return MM_ERROR_NONE;
+       }
        if (update_all_param || !g_strcmp0(param_name, "display_overlay"))
                __mmplayer_video_param_set_display_overlay(player);
        if (update_all_param || !g_strcmp0(param_name, "display_method"))
@@ -2122,19 +2200,15 @@ _mmplayer_update_video_overlay_param(mmplayer_t *player, const char *param_name)
        if (update_all_param)
                __mmplayer_video_param_set_video_roi_area(player);
 
-
        MMPLAYER_FLEAVE();
        return MM_ERROR_NONE;
 }
 
-int
-_mmplayer_set_audio_only(MMHandleType hplayer, bool audio_only)
+static int __mmplayer_set_disable_overlay_option(mmplayer_t *player, bool disable)
 {
        gboolean disable_overlay = FALSE;
-       mmplayer_t *player = (mmplayer_t *)hplayer;
 
        MMPLAYER_FENTER();
-       MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
        MMPLAYER_RETURN_VAL_IF_FAIL(player->pipeline->videobin &&
                                                                player->pipeline->videobin[MMPLAYER_V_SINK].gst,
                                                                MM_ERROR_PLAYER_NO_OP); /* invalid op */
@@ -2146,65 +2220,75 @@ _mmplayer_set_audio_only(MMHandleType hplayer, bool audio_only)
 
        g_object_get(player->pipeline->videobin[MMPLAYER_V_SINK].gst, "disable-overlay", &disable_overlay, NULL);
 
-       if (audio_only == (bool)disable_overlay) {
-               LOGE("It's the same with current setting: (%d)", audio_only);
+       if (disable == (bool)disable_overlay) {
+               LOGE("It's the same with current setting: (%d)", disable);
                return MM_ERROR_NONE;
        }
 
-       if (audio_only) {
+       if (disable) {
                LOGE("disable overlay");
                g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst, "disable-overlay", TRUE, NULL);
 
                /* release overlay resource */
                if (__mmplayer_release_hw_resource(player, MMPLAYER_RESOURCE_TYPE_VIDEO_OVERLAY) != MM_ERROR_NONE) {
                        LOGE("failed to release overlay resource");
-                       goto ERROR;
+                       return MM_ERROR_PLAYER_INTERNAL;
                }
        } else {
                if (_mmplayer_acquire_hw_resource(player, MMPLAYER_RESOURCE_TYPE_VIDEO_OVERLAY) != MM_ERROR_NONE) {
                        LOGE("failed to acquire video overlay resource");
-                       goto ERROR;
+                       return MM_ERROR_PLAYER_INTERNAL;
                }
                player->interrupted_by_resource = FALSE;
 
                LOGD("enable overlay");
                __mmplayer_video_param_set_display_overlay(player);
+               __mmplayer_video_param_set_display_overlay_sync_ui(player);
                g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst, "disable-overlay", FALSE, NULL);
        }
 
-ERROR:
        MMPLAYER_FLEAVE();
        return MM_ERROR_NONE;
 }
 
 int
-_mmplayer_get_audio_only(MMHandleType hplayer, bool *paudio_only)
+_mmplayer_set_audio_only(MMHandleType hplayer, bool audio_only)
 {
+       int ret = MM_ERROR_NONE;
        mmplayer_t *player = (mmplayer_t *)hplayer;
-       gboolean disable_overlay = FALSE;
 
        MMPLAYER_FENTER();
-
        MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
-       MMPLAYER_RETURN_VAL_IF_FAIL(paudio_only, MM_ERROR_INVALID_ARGUMENT);
-       MMPLAYER_RETURN_VAL_IF_FAIL(player->pipeline->videobin &&
-                                                               player->pipeline->videobin[MMPLAYER_V_SINK].gst,
-                                                               MM_ERROR_PLAYER_NO_OP); /* invalid op */
 
-       if (!g_object_class_find_property(G_OBJECT_GET_CLASS(player->pipeline->videobin[MMPLAYER_V_SINK].gst), "disable-overlay")) {
-               LOGW("Display control is not supported");
-               return MM_ERROR_PLAYER_INTERNAL;
+       if (MMPLAYER_USE_DECODEBIN(player)) {
+               ret = __mmplayer_set_disable_overlay_option(player, audio_only);
+               goto EXIT;
        }
 
-       g_object_get(player->pipeline->videobin[MMPLAYER_V_SINK].gst, "disable-overlay", &disable_overlay, NULL);
+       if (audio_only) {
+               MMPLAYER_RETURN_VAL_IF_FAIL(player->pipeline->videobin &&
+                                                                       player->pipeline->videobin[MMPLAYER_V_SINK].gst,
+                                                                       MM_ERROR_PLAYER_NO_OP); /* invalid op */
 
-       *paudio_only = (bool)disable_overlay;
+               __mmplayer_del_sink(player, player->pipeline->videobin[MMPLAYER_V_SINK].gst);
 
-       LOGD("audio_only : %d", *paudio_only);
+               __mmplayer_switch_stream(player, MM_PLAYER_TRACK_TYPE_VIDEO, INVALID_TRACK_INDEX);
 
-       MMPLAYER_FLEAVE();
+               /* release decoder resource */
+               if (__mmplayer_release_hw_resource(player, MMPLAYER_RESOURCE_TYPE_VIDEO_DECODER) != MM_ERROR_NONE) {
+                       LOGE("failed to release video decoder resources");
+                       return MM_ERROR_PLAYER_INTERNAL;
+               }
+               player->can_support_codec &= ~FOUND_PLUGIN_VIDEO;
+       } else {
+               __mmplayer_switch_stream(player, MM_PLAYER_TRACK_TYPE_VIDEO, DEFAULT_TRACK_INDEX);
+       }
 
-       return MM_ERROR_NONE;
+EXIT:
+       mm_player_set_attribute(hplayer, NULL, MM_PLAYER_AUDIO_ONLY, (int)audio_only, (char *)NULL);
+
+       MMPLAYER_FLEAVE();
+       return ret;
 }
 
 int
@@ -3004,7 +3088,7 @@ __mmplayer_gst_make_audio_extract_sink(mmplayer_t *player, GList **bucket)
                                MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "no-more-pads", G_CALLBACK(__mmplayer_gst_audio_deinterleave_no_more_pads), (gpointer)player);
                player->no_more_pad = FALSE;
        } else {
-       /* 4-2. create fakesink to extract interlevaed pcm */
+       /* 4-2. create fakesink to extract interleaved pcm */
                LOGD("add audio fakesink for interleaved audio");
                MMPLAYER_CREATE_ELEMENT(audiobin, extract_sink_id, "fakesink", "fakeaudiosink", *bucket, player);
                if (!(player->audio_extract_opt & MM_PLAYER_AUDIO_EXTRACT_NO_SYNC_WITH_CLOCK))
@@ -3264,6 +3348,7 @@ __mmplayer_video_stream_get_bo(mmplayer_t *player, int size)
        GList *l = NULL;
        MMPLAYER_RETURN_VAL_IF_FAIL(player, NULL);
        gboolean ret = TRUE;
+       gint64 end_time = 0;
 
        /* check DRC, if it is, destroy the prev bo list to create again */
        if (player->video_bo_size != size) {
@@ -3316,6 +3401,9 @@ __mmplayer_video_stream_get_bo(mmplayer_t *player, int size)
                }
        }
 
+       if (player->ini.video_bo_timeout > 0)
+               end_time = g_get_monotonic_time() + player->ini.video_bo_timeout * G_TIME_SPAN_SECOND;
+
        while (TRUE) {
                /* get bo from list*/
                for (l = g_list_first(player->video_bo_list); l; l = g_list_next(l)) {
@@ -3327,20 +3415,20 @@ __mmplayer_video_stream_get_bo(mmplayer_t *player, int size)
                                return tbm_bo_ref(tmp->bo);
                        }
                }
-               if (!ret) {
-                       LOGE("failed to get bo in %d timeout", player->ini.video_bo_timeout);
-                       MMPLAYER_VIDEO_BO_UNLOCK(player);
-                       return NULL;
-               }
 
                if (player->ini.video_bo_timeout <= 0) {
                        MMPLAYER_VIDEO_BO_WAIT(player);
                } else {
-                       gint64 timeout = g_get_monotonic_time() + player->ini.video_bo_timeout * G_TIME_SPAN_SECOND;
-                       ret = MMPLAYER_VIDEO_BO_WAIT_UNTIL(player, timeout);
+                       ret = MMPLAYER_VIDEO_BO_WAIT_UNTIL(player, end_time);
+                       if (!ret) {
+                               LOGE("failed to get bo in %d timeout", player->ini.video_bo_timeout);
+                               break;
+                       }
                }
-               continue;
        }
+
+       MMPLAYER_VIDEO_BO_UNLOCK(player);
+       return NULL;
 }
 
 static void
@@ -3511,7 +3599,9 @@ __mmplayer_gst_create_video_filters(mmplayer_t *player, MMDisplaySurfaceType sur
                goto EXIT;
        }
 
-       if (surface_type != MM_DISPLAY_SURFACE_OVERLAY || player->set_mode.video_zc) {
+       if ((surface_type != MM_DISPLAY_SURFACE_OVERLAY &&
+               surface_type != MM_DISPLAY_SURFACE_OVERLAY_SYNC_UI) ||
+               player->set_mode.video_zc) {
                LOGD("skip creating the videoconv and rotator");
                return MM_ERROR_NONE;
        }
@@ -3541,10 +3631,13 @@ __mmplayer_get_videosink_factory_name(mmplayer_t *player, MMDisplaySurfaceType s
 
        switch (surface_type) {
        case MM_DISPLAY_SURFACE_OVERLAY:
+       /* fall through */
+       case MM_DISPLAY_SURFACE_OVERLAY_SYNC_UI:
                if (strlen(player->ini.videosink_element_overlay) > 0)
                        factory_name = player->ini.videosink_element_overlay;
                break;
        case MM_DISPLAY_SURFACE_REMOTE:
+       /* fall through */
        case MM_DISPLAY_SURFACE_NULL:
                if (strlen(player->ini.videosink_element_fake) > 0)
                        factory_name = player->ini.videosink_element_fake;
@@ -3578,7 +3671,7 @@ __mmplayer_gst_set_videosink_property(mmplayer_t *player, MMDisplaySurfaceType s
                return MM_ERROR_PLAYER_INTERNAL;
        }
 
-       if (surface_type == MM_DISPLAY_SURFACE_OVERLAY) {
+       if (surface_type == MM_DISPLAY_SURFACE_OVERLAY || surface_type == MM_DISPLAY_SURFACE_OVERLAY_SYNC_UI) {
                bool use_tbm = (player->set_mode.video_zc || (player->is_360_feature_enabled && player->is_content_spherical));
                if (strncmp(factory_name, "tizenwlsink", strlen(factory_name)) == 0) {
                        g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst,
@@ -3772,7 +3865,6 @@ __mmplayer_gst_create_plain_text_elements(mmplayer_t *player)
        LOGD("adding created elements to bin");
        if (!_mmplayer_gst_element_add_bucket_to_bin(GST_BIN(textbin[MMPLAYER_T_BIN].gst), element_bucket)) {
                LOGE("failed to add elements");
-               g_list_free(element_bucket);
                goto ERROR;
        }
 
@@ -3784,13 +3876,9 @@ __mmplayer_gst_create_plain_text_elements(mmplayer_t *player)
        LOGD("Linking elements in the bucket by added order.");
        if (_mmplayer_gst_element_link_bucket(element_bucket) == -1) {
                LOGE("failed to link elements");
-               g_list_free(element_bucket);
                goto ERROR;
        }
 
-       /* done. free allocated variables */
-       g_list_free(element_bucket);
-
        if (textbin[MMPLAYER_T_QUEUE].gst) {
                GstPad *pad = NULL;
                GstPad *ghostpad = NULL;
@@ -3816,10 +3904,14 @@ __mmplayer_gst_create_plain_text_elements(mmplayer_t *player)
                }
        }
 
+       g_list_free(element_bucket);
+
        return MM_ERROR_NONE;
 
 ERROR:
 
+       g_list_free(element_bucket);
+
        if (!player->play_subtitle && textbin[MMPLAYER_T_FAKE_SINK].gst) {
                LOGE("remove textbin sink from sink list");
                __mmplayer_del_sink(player, textbin[MMPLAYER_T_FAKE_SINK].gst);
@@ -3833,7 +3925,6 @@ static int
 __mmplayer_gst_create_text_sink_bin(mmplayer_t *player)
 {
        mmplayer_gst_element_t *textbin = NULL;
-       GList *element_bucket = NULL;
        int surface_type = 0;
        gint i = 0;
 
@@ -3884,8 +3975,6 @@ ERROR:
 
        LOGD("ERROR : releasing textbin");
 
-       g_list_free(element_bucket);
-
        /* release signal */
        __mmplayer_release_signal_connection(player, MM_PLAYER_SIGNAL_TYPE_TEXTBIN);
 
@@ -4360,9 +4449,6 @@ __mmplayer_gst_destroy_pipeline(mmplayer_t *player)
                __mmplayer_release_signal_connection(player, MM_PLAYER_SIGNAL_TYPE_ALL);
 
                if (mainbin) {
-                       mmplayer_gst_element_t *audiobin = player->pipeline->audiobin;
-                       mmplayer_gst_element_t *videobin = player->pipeline->videobin;
-                       mmplayer_gst_element_t *textbin = player->pipeline->textbin;
                        GstBus *bus = gst_pipeline_get_bus(GST_PIPELINE(mainbin[MMPLAYER_M_PIPE].gst));
                        gst_bus_set_sync_handler(bus, NULL, NULL, NULL);
                        gst_object_unref(bus);
@@ -4382,9 +4468,9 @@ __mmplayer_gst_destroy_pipeline(mmplayer_t *player)
                        if (mainbin[MMPLAYER_M_SRC_FAKESINK].gst)
                                gst_object_unref(GST_OBJECT(mainbin[MMPLAYER_M_SRC_FAKESINK].gst));
 
-                       MMPLAYER_FREEIF(audiobin);
-                       MMPLAYER_FREEIF(videobin);
-                       MMPLAYER_FREEIF(textbin);
+                       MMPLAYER_FREEIF(player->pipeline->audiobin);
+                       MMPLAYER_FREEIF(player->pipeline->videobin);
+                       MMPLAYER_FREEIF(player->pipeline->textbin);
                        MMPLAYER_FREEIF(mainbin);
                }
 
@@ -4610,6 +4696,8 @@ __resource_release_cb(mm_resource_manager_h rm, mm_resource_manager_res_h res,
 
        player->interrupted_by_resource = TRUE;
 
+       MMPLAYER_POST_MSG(player, MM_MESSAGE_INTERRUPT_STARTED, NULL);
+
        /* get last play position */
        if (_mmplayer_gst_get_position(player, &pos) == MM_ERROR_NONE) {
                msg.union_type = MM_MSG_UNION_TIME;
@@ -4710,8 +4798,8 @@ _mmplayer_create_player(MMHandleType handle)
 
        ret = _mmplayer_initialize_video_capture(player);
        if (ret != MM_ERROR_NONE) {
-               LOGE("failed to initialize video capture");
-               goto ERROR;
+               LOGW("video capture is not supported");
+               /* do not handle as error for headless profile */
        }
 
        /* initialize resource manager */
@@ -5665,11 +5753,24 @@ _mmplayer_abort_pause(MMHandleType hplayer)
                                                player->pipeline->mainbin,
                                                MM_ERROR_PLAYER_NOT_INITIALIZED);
 
-       LOGD("set the pipeline state to READY");
+       if (player->pipeline->videobin && player->pipeline->videobin[MMPLAYER_V_BIN].gst) {
+               LOGD("set the videobin state to READY");
+               ret = _mmplayer_gst_set_state(player, player->pipeline->videobin[MMPLAYER_V_BIN].gst,
+                                                       GST_STATE_READY, TRUE, MMPLAYER_STATE_CHANGE_TIMEOUT(player));
+
+       }
+
+       if (player->pipeline->audiobin && player->pipeline->audiobin[MMPLAYER_A_BIN].gst) {
+               LOGD("set the audiobin state to READY");
+               ret = _mmplayer_gst_set_state(player, player->pipeline->audiobin[MMPLAYER_A_BIN].gst,
+                                                       GST_STATE_READY, TRUE, MMPLAYER_STATE_CHANGE_TIMEOUT(player));
+
+       }
 
-       /* set state to READY */
+       LOGD("set the pipeline state to READY");
        ret = _mmplayer_gst_set_state(player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst,
                                                GST_STATE_READY, FALSE, MMPLAYER_STATE_CHANGE_TIMEOUT(player));
+
        if (ret != MM_ERROR_NONE) {
                LOGE("fail to change state to READY");
                return MM_ERROR_PLAYER_INTERNAL;
@@ -6247,8 +6348,10 @@ ERROR:
                /* And, it still has a parent "player".
                 * You need to let the parent manage the object instead of unreffing the object directly.
                 */
-               gst_bin_remove(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), queue2);
-               gst_object_unref(queue2);
+               if (!gst_bin_remove(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), queue2)) {
+                       LOGE("failed to remove queue2");
+                       gst_object_unref(queue2);
+               }
                queue2 = NULL;
        }
 
@@ -6263,8 +6366,10 @@ ERROR:
                 * You need to let the parent manage the object instead of unreffing the object directly.
                 */
 
-               gst_bin_remove(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), decodebin);
-               gst_object_unref(decodebin);
+               if (!gst_bin_remove(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), decodebin)) {
+                       LOGE("failed to remove decodebin");
+                       gst_object_unref(decodebin);
+               }
                decodebin = NULL;
        }
 
@@ -6680,7 +6785,11 @@ __mmplayer_deactivate_selector(mmplayer_t *player, mmplayer_track_type_e type)
                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);
+               if (!gst_bin_remove(GST_BIN_CAST(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst),
+                                                       player->pipeline->mainbin[selectorId].gst)) {
+                       LOGE("failed to remove selector");
+                       gst_object_unref(player->pipeline->mainbin[selectorId].gst);
+               }
 
                player->pipeline->mainbin[selectorId].gst = NULL;
                selector = NULL;
@@ -6906,8 +7015,13 @@ _mmplayer_gst_decode_autoplug_continue(GstElement *bin, GstPad *pad,
 
                MMPLAYER_FREEIF(caps_str);
        } else if (g_str_has_prefix(mime, "video") && player->videodec_linked) {
-               LOGD("already video linked");
-               ret = FALSE;
+               if((MMPLAYER_IS_HTTP_LIVE_STREAMING(player)) || (MMPLAYER_IS_DASH_STREAMING(player))) {
+                       LOGD("video is already linked, allow the stream switch");
+                       ret = TRUE;
+               } else {
+                       LOGD("video is already linked");
+                       ret = FALSE;
+               }
        } else {
                LOGD("found new stream");
        }
@@ -7464,27 +7578,51 @@ DONE:
 }
 
 void
-_mmplayer_gst_decode_pad_removed(GstElement *elem, GstPad *new_pad,
+_mmplayer_gst_decode_pad_removed(GstElement *elem, GstPad *pad,
        gpointer data)
 {
-       //mmplayer_t *player = (mmplayer_t *)data;
-       GstCaps *caps = NULL;
+       int ret = MM_ERROR_NONE;
+       mmplayer_t *player = (mmplayer_t *)data;
+       mmplayer_gst_element_t *mainbin = player->pipeline->mainbin;
+       mmplayer_gst_element_t *videobin = player->pipeline->videobin;
 
-       LOGD("[Decodebin2] pad-removed signal");
+       MMPLAYER_FENTER();
+       MMPLAYER_RETURN_IF_FAIL(player && player->pipeline && mainbin);
 
-       caps = gst_pad_query_caps(new_pad, NULL);
-       if (!caps) {
-               LOGW("query caps is NULL");
+       LOGD("decoded pad %s:%s removed", GST_DEBUG_PAD_NAME(pad));
+
+       if (MMPLAYER_USE_DECODEBIN(player))
+               return;
+
+       if (!videobin || !g_str_has_prefix(GST_PAD_NAME (pad), "video"))
                return;
+
+       __mmplayer_release_signal_connection(player, MM_PLAYER_SIGNAL_TYPE_VIDEOBIN);
+
+       __mmplayer_del_sink(player, videobin[MMPLAYER_V_SINK].gst);
+
+       if (!gst_bin_remove(GST_BIN_CAST(mainbin[MMPLAYER_M_PIPE].gst), videobin[MMPLAYER_V_BIN].gst)) {
+               LOGE("failed to remove videobin");
+               gst_object_unref(GST_OBJECT(videobin[MMPLAYER_V_BIN].gst));
        }
 
-       gchar *caps_str = NULL;
-       caps_str = gst_caps_to_string(caps);
+       if (!gst_bin_remove(GST_BIN_CAST(mainbin[MMPLAYER_M_PIPE].gst), mainbin[MMPLAYER_M_V_CONCAT].gst)) {
+               LOGE("failed to remove video concat");
+               gst_object_unref(GST_OBJECT(mainbin[MMPLAYER_M_V_CONCAT].gst));
+       }
 
-       LOGD("pad removed caps : %s from %s", caps_str, GST_ELEMENT_NAME(elem));
+       mainbin[MMPLAYER_M_V_CONCAT].gst = NULL;
+       mainbin[MMPLAYER_M_V_CONCAT].id = 0;
+       MMPLAYER_FREEIF(player->pipeline->videobin);
 
-       MMPLAYER_FREEIF(caps_str);
-       gst_caps_unref(caps);
+       ret = __mmplayer_release_hw_resource(player, MMPLAYER_RESOURCE_TYPE_VIDEO_OVERLAY);
+       if (ret != MM_ERROR_NONE)
+               LOGE("failed to release overlay resources");
+
+       player->videodec_linked = 0;
+
+       MMPLAYER_GENERATE_DOT_IF_ENABLED(player, "pipeline-pad-removed");
+       MMPLAYER_FLEAVE();
 }
 
 void
@@ -7511,7 +7649,7 @@ _mmplayer_gst_about_to_finish(GstElement *bin, gpointer data)
        _mmplayer_set_reconfigure_state(player, TRUE);
        MMPLAYER_CMD_UNLOCK(player);
 
-       MMPLAYER_POST_MSG(player, MM_MESSAGE_GAPLESS_CONSTRUCTION, NULL);
+       MMPLAYER_POST_MSG(player, MM_MESSAGE_FLUSH_BUFFER, NULL);
        __mmplayer_deactivate_old_path(player);
 
        MMPLAYER_FLEAVE();
@@ -7582,7 +7720,7 @@ _mmplayer_gst_decode_drained(GstElement *bin, gpointer data)
        player->gapless.update_segment[MM_PLAYER_TRACK_TYPE_VIDEO] = FALSE;
 
        /* 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_POST_MSG(player, MM_MESSAGE_FLUSH_BUFFER, NULL); /* post message for gapless */
        __mmplayer_deactivate_old_path(player);
 
        MMPLAYER_FLEAVE();
@@ -7637,6 +7775,9 @@ _mmplayer_gst_element_added(GstElement *bin, GstElement *element, gpointer data)
 #endif
                player->pipeline->mainbin[MMPLAYER_M_DEMUX].id = MMPLAYER_M_DEMUX;
                player->pipeline->mainbin[MMPLAYER_M_DEMUX].gst = element;
+       } else if (g_strrstr(klass, "Parser") && (g_strrstr(klass, "Video"))) {
+               player->pipeline->mainbin[MMPLAYER_M_V_PARSE].id = MMPLAYER_M_V_PARSE;
+               player->pipeline->mainbin[MMPLAYER_M_V_PARSE].gst = element;
        }
 
        if (g_strrstr(factory_name, "asfdemux") || g_strrstr(factory_name, "qtdemux") || g_strrstr(factory_name, "avidemux")) {
@@ -7662,6 +7803,14 @@ _mmplayer_gst_element_added(GstElement *bin, GstElement *element, gpointer data)
                player->pipeline->mainbin[MMPLAYER_M_DEC1].gst = element;
        }
 
+       if (g_strrstr(factory_name, "omxdec_h264") || g_strrstr(factory_name, "v4l2h264dec")) {
+               GstElement *video_parse = player->pipeline->mainbin[MMPLAYER_M_V_PARSE].gst;
+               if (video_parse && (g_object_class_find_property(G_OBJECT_GET_CLASS(video_parse), "config-interval"))) {
+                       g_object_set(G_OBJECT(video_parse), "config-interval", -1, NULL);
+                       LOGD("Send SPS and PPS Insertion every IDR frame");
+               }
+       }
+
        if ((player->pipeline->mainbin[MMPLAYER_M_DEMUX].gst) &&
                (g_strrstr(GST_ELEMENT_NAME(element), "multiqueue"))) {
                LOGD("plugged element is multiqueue. take it %s", GST_ELEMENT_NAME(element));
@@ -7784,7 +7933,8 @@ __mmplayer_release_misc_post(mmplayer_t *player)
        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);
+       mm_player_set_attribute((MMHandleType)player, NULL,
+               "content_video_found", 0, MM_PLAYER_AUDIO_ONLY, 0, NULL);
 
        /* clean found audio decoders */
        if (player->audio_decoders) {
@@ -7966,7 +8116,7 @@ __mmplayer_release_signal_connection(mmplayer_t *player, mmplayer_signal_type_e
        for (; sig_list; sig_list = sig_list->next) {
                item = sig_list->data;
 
-               if (item && item->obj && GST_IS_ELEMENT(item->obj)) {
+               if (item && item->obj) {
                        if (g_signal_handler_is_connected(item->obj, item->sig))
                                g_signal_handler_disconnect(item->obj, item->sig);
                }
@@ -8344,16 +8494,19 @@ __mmplayer_switch_stream(mmplayer_t *player, mmplayer_track_type_e type, int ind
        guint active_idx = 0;
        GstStream *stream = NULL;
        GList *streams = NULL;
-       GstEvent *ev = NULL;
        GstCaps *caps = NULL;
 
+       MMPLAYER_FENTER();
        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) {
+               LOGD("track type:%d, total: %d, active: %d", i,
+                               player->track[i].total_track_num, player->track[i].active_track_index);
+               if (player->track[i].total_track_num > 0 &&
+                       player->track[i].active_track_index > INVALID_TRACK_INDEX) {
                        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));
@@ -8369,10 +8522,32 @@ __mmplayer_switch_stream(mmplayer_t *player, mmplayer_track_type_e type, int ind
                }
        }
 
-       ev = gst_event_new_select_streams(streams);
-       gst_element_send_event(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, ev);
-       g_list_free(streams);
+       if (streams) {
+               LOGD("send select stream event");
+               gst_element_send_event(player->pipeline->mainbin[MMPLAYER_M_AUTOPLUG].gst,
+                               gst_event_new_select_streams(streams));
+               g_list_free(streams);
+       }
+
+       /* in paused state, seek to current pos to flush mq buffer and release waiting task */
+       if (MMPLAYER_CURRENT_STATE(player) == MM_PLAYER_STATE_PAUSED) {
+               gint64 pos_nsec = GST_CLOCK_TIME_NONE;
+
+               if (!gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &pos_nsec))
+                       pos_nsec = player->last_position;
 
+               LOGD("current pos %" GST_TIME_FORMAT ", rate = %f", GST_TIME_ARGS(pos_nsec), player->playback_rate);
+
+               if (!_mmplayer_gst_seek(player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst,
+                                       player->playback_rate, GST_FORMAT_TIME,
+                                       (GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE),
+                                       GST_SEEK_TYPE_SET, pos_nsec, GST_SEEK_TYPE_SET, GST_CLOCK_TIME_NONE)) {
+                       LOGW("failed to seek");
+                       return MM_ERROR_PLAYER_INTERNAL;
+               }
+       }
+
+       MMPLAYER_FLEAVE();
        return MM_ERROR_NONE;
 }
 
@@ -9235,9 +9410,6 @@ __mmplayer_update_audio_attrs(mmplayer_t *player, MMHandleType attrs)
        }
 
        p = gst_caps_get_structure(caps_a, 0);
-
-       mm_attrs_get_int_by_name(attrs, "content_audio_samplerate", &samplerate);
-
        gst_structure_get_int(p, "rate", &samplerate);
        gst_structure_get_int(p, "channels", &channels);