Add sink_msg_callback function.
[platform/core/multimedia/libmm-wfd.git] / src / mm_wfd_sink_priv.c
index d6ccfd3..e960c2a 100644 (file)
 #include "mm_wfd_sink_enum.h"
 #include "mm_wfd_sink_wayland.h"
 
+#define PRINT_WFD_REF_COUNT(wfd_sink)\
+       do {\
+               wfd_sink_debug("PRINT WFD REF COUNT");\
+               __mm_wfd_sink_print_ref_count(wfd_sink);\
+       } while (0);
+
 /* gstreamer */
 static int __mm_wfd_sink_init_gstreamer(mm_wfd_sink_t *wfd_sink);
 static int __mm_wfd_sink_create_pipeline(mm_wfd_sink_t *wfd_sink);
 static int __mm_wfd_sink_destroy_audio_decodebin(mm_wfd_sink_t *wfd_sink);
 static int __mm_wfd_sink_destroy_video_decodebin(mm_wfd_sink_t *wfd_sink);
+static int __mm_wfd_sink_destroy_audio_sinkbin(mm_wfd_sink_t *wfd_sink);
+static int __mm_wfd_sink_destroy_video_sinkbin(mm_wfd_sink_t *wfd_sink);
 static int __mm_wfd_sink_destroy_pipeline(mm_wfd_sink_t *wfd_sink);
 static int __mm_wfd_sink_set_pipeline_state(mm_wfd_sink_t *wfd_sink, GstState state, gboolean async);
+static gboolean _mm_wfd_sink_msg_callback(GstBus *bus, GstMessage *msg, gpointer data);
 
 /* state */
 static int __mm_wfd_sink_set_state(mm_wfd_sink_t *wfd_sink, MMWFDSinkStateType state);
@@ -239,15 +248,15 @@ int _mm_wfd_sink_connect(mm_wfd_sink_t *wfd_sink, const char *uri)
        wfd_sink_debug_fenter();
 
        wfd_sink_return_val_if_fail(uri && strlen(uri) > strlen("rtsp://"),
-                                               MM_ERROR_WFD_INVALID_ARGUMENT);
+                                                               MM_ERROR_WFD_INVALID_ARGUMENT);
        wfd_sink_return_val_if_fail(wfd_sink &&
-                                               wfd_sink->pipeline &&
-                                               wfd_sink->pipeline->mainbin &&
-                                               wfd_sink->pipeline->mainbin[WFD_SINK_M_PIPE].gst &&
-                                               wfd_sink->pipeline->mainbin[WFD_SINK_M_SRC].gst &&
-                                               wfd_sink->pipeline->mainbin[WFD_SINK_M_DEPAY].gst &&
-                                               wfd_sink->pipeline->mainbin[WFD_SINK_M_DEMUX].gst,
-                                               MM_ERROR_WFD_NOT_INITIALIZED);
+                                                               wfd_sink->pipeline &&
+                                                               wfd_sink->pipeline->mainbin &&
+                                                               wfd_sink->pipeline->mainbin[WFD_SINK_M_PIPE].gst &&
+                                                               wfd_sink->pipeline->mainbin[WFD_SINK_M_SRC].gst &&
+                                                               wfd_sink->pipeline->mainbin[WFD_SINK_M_DEPAY].gst &&
+                                                               wfd_sink->pipeline->mainbin[WFD_SINK_M_DEMUX].gst,
+                                                               MM_ERROR_WFD_NOT_INITIALIZED);
 
        /* check current wi-fi display sink state */
        MMWFDSINK_CHECK_STATE(wfd_sink, MM_WFD_SINK_COMMAND_CONNECT);
@@ -302,11 +311,11 @@ int _mm_wfd_sink_pause(mm_wfd_sink_t *wfd_sink)
        wfd_sink_debug_fenter();
 
        wfd_sink_return_val_if_fail(wfd_sink &&
-                                               wfd_sink->pipeline &&
-                                               wfd_sink->pipeline->mainbin &&
-                                               wfd_sink->pipeline->mainbin[WFD_SINK_M_PIPE].gst &&
-                                               wfd_sink->pipeline->mainbin[WFD_SINK_M_SRC].gst,
-                                               MM_ERROR_WFD_NOT_INITIALIZED);
+                                                               wfd_sink->pipeline &&
+                                                               wfd_sink->pipeline->mainbin &&
+                                                               wfd_sink->pipeline->mainbin[WFD_SINK_M_PIPE].gst &&
+                                                               wfd_sink->pipeline->mainbin[WFD_SINK_M_SRC].gst,
+                                                               MM_ERROR_WFD_NOT_INITIALIZED);
 
        /* check current wi-fi display sink state */
        MMWFDSINK_CHECK_STATE(wfd_sink, MM_WFD_SINK_COMMAND_PAUSE);
@@ -325,11 +334,11 @@ int _mm_wfd_sink_resume(mm_wfd_sink_t *wfd_sink)
        wfd_sink_debug_fenter();
 
        wfd_sink_return_val_if_fail(wfd_sink &&
-                                               wfd_sink->pipeline &&
-                                               wfd_sink->pipeline->mainbin &&
-                                               wfd_sink->pipeline->mainbin[WFD_SINK_M_PIPE].gst &&
-                                               wfd_sink->pipeline->mainbin[WFD_SINK_M_SRC].gst,
-                                               MM_ERROR_WFD_NOT_INITIALIZED);
+                                                               wfd_sink->pipeline &&
+                                                               wfd_sink->pipeline->mainbin &&
+                                                               wfd_sink->pipeline->mainbin[WFD_SINK_M_PIPE].gst &&
+                                                               wfd_sink->pipeline->mainbin[WFD_SINK_M_SRC].gst,
+                                                               MM_ERROR_WFD_NOT_INITIALIZED);
 
        /* check current wi-fi display sink state */
        MMWFDSINK_CHECK_STATE(wfd_sink, MM_WFD_SINK_COMMAND_RESUME);
@@ -348,11 +357,11 @@ int _mm_wfd_sink_disconnect(mm_wfd_sink_t *wfd_sink)
        wfd_sink_debug_fenter();
 
        wfd_sink_return_val_if_fail(wfd_sink &&
-                                               wfd_sink->pipeline &&
-                                               wfd_sink->pipeline->mainbin &&
-                                               wfd_sink->pipeline->mainbin[WFD_SINK_M_PIPE].gst &&
-                                               wfd_sink->pipeline->mainbin[WFD_SINK_M_SRC].gst,
-                                               MM_ERROR_WFD_NOT_INITIALIZED);
+                                                               wfd_sink->pipeline &&
+                                                               wfd_sink->pipeline->mainbin &&
+                                                               wfd_sink->pipeline->mainbin[WFD_SINK_M_PIPE].gst &&
+                                                               wfd_sink->pipeline->mainbin[WFD_SINK_M_SRC].gst,
+                                                               MM_ERROR_WFD_NOT_INITIALIZED);
 
        /* check current wi-fi display sink state */
        MMWFDSINK_CHECK_STATE(wfd_sink, MM_WFD_SINK_COMMAND_DISCONNECT);
@@ -498,7 +507,7 @@ static int __mm_wfd_sink_init_gstreamer(mm_wfd_sink_t *wfd_sink)
        /* initializing gstreamer */
        if (!gst_init_check(argc, &argv, &err)) {
                wfd_sink_error("failed to initialize gstreamer: %s",
-                                       err ? err->message : "unknown error occurred");
+                                               err ? err->message : "unknown error occurred");
                if (err)
                        g_error_free(err);
 
@@ -523,36 +532,257 @@ _mm_wfd_bus_sync_callback(GstBus *bus, GstMessage *message, gpointer data)
        GstBusSyncReply ret = GST_BUS_PASS;
 
        wfd_sink_return_val_if_fail(message &&
-                                               GST_IS_MESSAGE(message) &&
-                                               GST_MESSAGE_SRC(message),
-                                               GST_BUS_DROP);
+                                                               GST_IS_MESSAGE(message) &&
+                                                               GST_MESSAGE_SRC(message),
+                                                               GST_BUS_DROP);
 
        wfd_sink_debug("get message %p, %s from %p, %s", message,
-                       GST_MESSAGE_TYPE_NAME(message), GST_MESSAGE_SRC(message), GST_MESSAGE_SRC_NAME(message));
+                                       GST_MESSAGE_TYPE_NAME(message), GST_MESSAGE_SRC(message), GST_MESSAGE_SRC_NAME(message));
 
        switch (GST_MESSAGE_TYPE(message)) {
-               case GST_MESSAGE_TAG:
-                       break;
-               case GST_MESSAGE_DURATION:
-                       break;
-               case GST_MESSAGE_STATE_CHANGED: {
-                               /* we only handle state change messages from pipeline */
-                               if (!GST_IS_PIPELINE(GST_MESSAGE_SRC(message)))
-                                       ret = GST_BUS_DROP;
-                       }
-                       break;
-               case GST_MESSAGE_ASYNC_DONE: {
-                               if (!GST_IS_PIPELINE(GST_MESSAGE_SRC(message)))
-                                       ret = GST_BUS_DROP;
-                       }
-                       break;
-               default:
-                       break;
+       case GST_MESSAGE_TAG:
+               break;
+       case GST_MESSAGE_DURATION:
+               break;
+       case GST_MESSAGE_STATE_CHANGED:
+               /* we only handle state change messages from pipeline */
+               if (GST_IS_PIPELINE(GST_MESSAGE_SRC(message)))
+                       _mm_wfd_sink_msg_callback(bus, message, data);
+
+               ret = GST_BUS_DROP;
+               break;
+       case GST_MESSAGE_ASYNC_DONE:
+               if (GST_IS_PIPELINE(GST_MESSAGE_SRC(message)))
+                       _mm_wfd_sink_msg_callback(bus, message, data);
+
+               ret = GST_BUS_DROP;
+               break;
+       default:
+               break;
+       }
+
+       if (ret == GST_BUS_DROP) {
+               gst_message_unref(message);
+               message = NULL;
        }
 
        return ret;
 }
 
+int __mm_wfd_sink_activate_audio_stream(mm_wfd_sink_t *wfd_sink)
+{
+       GstElement *valve = NULL;
+       GstPad *sinkpad = NULL;
+       GstPad *srcpad = NULL;
+       int result = MM_ERROR_NONE;
+
+       wfd_sink_debug_fenter();
+
+       wfd_sink_return_val_if_fail(wfd_sink &&
+                                                               wfd_sink->pipeline &&
+                                                               wfd_sink->pipeline->mainbin &&
+                                                               wfd_sink->pipeline->mainbin[WFD_SINK_M_PIPE].gst &&
+                                                               wfd_sink->pipeline->mainbin[WFD_SINK_M_A_VALVE].gst,
+                                                               MM_ERROR_WFD_NOT_INITIALIZED);
+
+       valve = wfd_sink->pipeline->mainbin[WFD_SINK_M_A_VALVE].gst;
+       srcpad = gst_element_get_static_pad(valve, "src");
+       if (!srcpad) {
+               wfd_sink_error("failed to get src pad from %s", GST_ELEMENT_NAME(valve));
+               goto error;
+       }
+
+       if (gst_pad_is_linked(srcpad)) {
+               wfd_sink_debug("%s:%s is already linked to %s:%s",
+                                               GST_ELEMENT_NAME(GST_PAD_PARENT(srcpad)), GST_PAD_NAME(srcpad));
+               goto done;
+       }
+
+       result = __mm_wfd_sink_prepare_audio_pipeline(wfd_sink, &sinkpad);
+       if (MM_ERROR_NONE != result) {
+               wfd_sink_error("failed to prepare audio pipeline....");
+               goto error;
+       }
+
+       wfd_sink_debug("try to link %s:%s and %s:%s",
+                                       GST_ELEMENT_NAME(GST_PAD_PARENT(srcpad)), GST_PAD_NAME(srcpad),
+                                       GST_ELEMENT_NAME(GST_PAD_PARENT(sinkpad)), GST_PAD_NAME(sinkpad));
+       if (GST_PAD_LINK_OK != gst_pad_link_full(srcpad, sinkpad, GST_PAD_LINK_CHECK_NOTHING)) {
+               wfd_sink_error("failed to link %s:%s and %s:%s",
+                                               GST_ELEMENT_NAME(GST_PAD_PARENT(srcpad)), GST_PAD_NAME(srcpad),
+                                               GST_ELEMENT_NAME(GST_PAD_PARENT(sinkpad)), GST_PAD_NAME(sinkpad));
+               goto error;
+       }
+
+       if (sinkpad != NULL) {
+               gst_object_unref(GST_OBJECT(sinkpad));
+               sinkpad = NULL;
+       }
+
+done:
+       if (srcpad != NULL) {
+               gst_object_unref(GST_OBJECT(srcpad));
+               srcpad = NULL;
+       }
+       /* drop all the audio buffers using valve */
+       g_object_set(G_OBJECT(valve), "drop", FALSE, NULL);
+
+       wfd_sink_debug_fleave();
+
+       return MM_ERROR_NONE;
+
+error:
+       if (srcpad != NULL) {
+               gst_object_unref(GST_OBJECT(srcpad));
+               srcpad = NULL;
+       }
+
+       if (sinkpad != NULL) {
+               gst_object_unref(GST_OBJECT(sinkpad));
+               sinkpad = NULL;
+       }
+
+       wfd_sink_debug_fleave();
+       return MM_ERROR_WFD_INTERNAL;
+}
+
+int __mm_wfd_sink_activate_video_stream(mm_wfd_sink_t *wfd_sink)
+{
+       GstElement *valve = NULL;
+       GstPad *sinkpad = NULL;
+       GstPad *srcpad = NULL;
+       int result = MM_ERROR_NONE;
+
+       wfd_sink_debug_fenter();
+
+       wfd_sink_return_val_if_fail(wfd_sink &&
+                                                               wfd_sink->pipeline &&
+                                                               wfd_sink->pipeline->mainbin &&
+                                                               wfd_sink->pipeline->mainbin[WFD_SINK_M_PIPE].gst &&
+                                                               wfd_sink->pipeline->mainbin[WFD_SINK_M_V_VALVE].gst,
+                                                               MM_ERROR_WFD_NOT_INITIALIZED);
+
+       valve = wfd_sink->pipeline->mainbin[WFD_SINK_M_V_VALVE].gst;
+       srcpad = gst_element_get_static_pad(valve, "src");
+       if (!srcpad) {
+               wfd_sink_error("failed to get src pad from %s", GST_ELEMENT_NAME(valve));
+               goto error;
+       }
+
+       if (gst_pad_is_linked(srcpad)) {
+               wfd_sink_debug("%s is already linked",
+                                               GST_ELEMENT_NAME(GST_PAD_PARENT(sinkpad)), GST_PAD_NAME(sinkpad));
+               goto done;
+       }
+
+       result = __mm_wfd_sink_prepare_video_pipeline(wfd_sink, &sinkpad);
+       if (MM_ERROR_NONE != result) {
+               wfd_sink_error("failed to prepare video pipeline....");
+               goto error;
+       }
+
+       wfd_sink_debug("try to link %s:%s and %s:%s",
+                                       GST_ELEMENT_NAME(GST_PAD_PARENT(srcpad)), GST_PAD_NAME(srcpad),
+                                       GST_ELEMENT_NAME(GST_PAD_PARENT(sinkpad)), GST_PAD_NAME(sinkpad));
+       if (GST_PAD_LINK_OK != gst_pad_link_full(srcpad, sinkpad, GST_PAD_LINK_CHECK_NOTHING)) {
+               wfd_sink_error("failed to link %s:%s and %s:%s",
+                                               GST_ELEMENT_NAME(GST_PAD_PARENT(srcpad)), GST_PAD_NAME(srcpad),
+                                               GST_ELEMENT_NAME(GST_PAD_PARENT(sinkpad)), GST_PAD_NAME(sinkpad));
+               goto error;
+       }
+       if (sinkpad != NULL) {
+               gst_object_unref(GST_OBJECT(sinkpad));
+               sinkpad = NULL;
+       }
+
+done:
+       if (srcpad != NULL) {
+               gst_object_unref(GST_OBJECT(srcpad));
+               srcpad = NULL;
+       }
+       /* drop all the video buffers using valve */
+       g_object_set(G_OBJECT(valve), "drop", FALSE, NULL);
+
+       wfd_sink_debug_fleave();
+
+       return MM_ERROR_NONE;
+
+error:
+       if (srcpad != NULL) {
+               gst_object_unref(GST_OBJECT(srcpad));
+               srcpad = NULL;
+       }
+
+       if (sinkpad != NULL) {
+               gst_object_unref(GST_OBJECT(sinkpad));
+               sinkpad = NULL;
+       }
+
+       wfd_sink_debug_fleave();
+       return MM_ERROR_WFD_INTERNAL;
+}
+
+int __mm_wfd_sink_deactivate_audio_stream(mm_wfd_sink_t *wfd_sink, gboolean unprepare)
+{
+       int ret = MM_ERROR_NONE;
+
+       wfd_sink_debug_fenter();
+
+       wfd_sink_return_val_if_fail(wfd_sink &&
+                                                               wfd_sink->pipeline &&
+                                                               wfd_sink->pipeline->mainbin &&
+                                                               wfd_sink->pipeline->mainbin[WFD_SINK_M_PIPE].gst &&
+                                                               wfd_sink->pipeline->mainbin[WFD_SINK_M_A_VALVE].gst,
+                                                               MM_ERROR_WFD_NOT_INITIALIZED);
+
+       /* drop all the audio buffers using valve */
+       g_object_set(G_OBJECT(wfd_sink->pipeline->mainbin[WFD_SINK_M_A_VALVE].gst), "drop", TRUE, NULL);
+
+       if (unprepare) {
+               /* unprepare audio pipeline */
+               ret = __mm_wfd_sink_unprepare_audio_pipeline(wfd_sink);
+               if (ret != MM_ERROR_NONE) {
+                       wfd_sink_error("failed to unprepare audio pipeline...");
+                       return MM_ERROR_WFD_INTERNAL;
+               }
+       }
+
+       wfd_sink_debug_fleave();
+
+       return MM_ERROR_NONE;
+}
+
+int __mm_wfd_sink_deactivate_video_stream(mm_wfd_sink_t *wfd_sink, gboolean unprepare)
+{
+       int ret = MM_ERROR_NONE;
+
+       wfd_sink_debug_fenter();
+
+       wfd_sink_return_val_if_fail(wfd_sink &&
+                                                               wfd_sink->pipeline &&
+                                                               wfd_sink->pipeline->mainbin &&
+                                                               wfd_sink->pipeline->mainbin[WFD_SINK_M_PIPE].gst &&
+                                                               wfd_sink->pipeline->mainbin[WFD_SINK_M_V_VALVE].gst,
+                                                               MM_ERROR_WFD_NOT_INITIALIZED);
+
+       /* drop all the video buffers using valve */
+       g_object_set(G_OBJECT(wfd_sink->pipeline->mainbin[WFD_SINK_M_V_VALVE].gst), "drop", TRUE, NULL);
+
+       if (unprepare) {
+               /* unprepare video pipeline */
+               ret = __mm_wfd_sink_unprepare_video_pipeline(wfd_sink);
+               if (ret != MM_ERROR_NONE) {
+                       wfd_sink_error("failed to unprepare video pipeline...");
+                       return MM_ERROR_WFD_INTERNAL;
+               }
+       }
+
+       wfd_sink_debug_fleave();
+
+       return MM_ERROR_NONE;
+
+}
+
 static gboolean
 _mm_wfd_sink_msg_callback(GstBus *bus, GstMessage *msg, gpointer data)
 {
@@ -662,14 +892,14 @@ _mm_wfd_sink_msg_callback(GstBus *bus, GstMessage *msg, gpointer data)
                        if (wfd_sink->clock) {
                                if (wfd_sink->clock != clock)
                                        wfd_sink_debug("clock is changed! [%s] -->[%s]",
-                                                       GST_STR_NULL(GST_OBJECT_NAME(wfd_sink->clock)),
-                                                       GST_STR_NULL(GST_OBJECT_NAME(clock)));
+                                                                       GST_STR_NULL(GST_OBJECT_NAME(wfd_sink->clock)),
+                                                                       GST_STR_NULL(GST_OBJECT_NAME(clock)));
                                else
                                        wfd_sink_debug("same clock is selected again! [%s]",
-                                                       GST_STR_NULL(GST_OBJECT_NAME(clock)));
+                                                                       GST_STR_NULL(GST_OBJECT_NAME(clock)));
                        } else {
                                wfd_sink_debug("new clock [%s] was selected in the pipeline",
-                                                       (GST_STR_NULL(GST_OBJECT_NAME(clock))));
+                                                               (GST_STR_NULL(GST_OBJECT_NAME(clock))));
                        }
 
                        wfd_sink->clock = clock;
@@ -825,14 +1055,14 @@ __mm_wfd_sink_gst_element_add_bucket_to_bin(GstBin *bin, GList *element_bucket,
 
                        if (!gst_bin_add(GST_BIN(bin), GST_ELEMENT(element->gst))) {
                                wfd_sink_error("failed to add element [%s] to bin [%s]",
-                                               GST_STR_NULL(GST_ELEMENT_NAME(GST_ELEMENT(element->gst))),
-                                               GST_STR_NULL(GST_ELEMENT_NAME(GST_ELEMENT_CAST(bin))));
+                                                               GST_STR_NULL(GST_ELEMENT_NAME(GST_ELEMENT(element->gst))),
+                                                               GST_STR_NULL(GST_ELEMENT_NAME(GST_ELEMENT_CAST(bin))));
                                return 0;
                        }
 
                        wfd_sink_debug("add element [%s] to bin [%s]",
-                                               GST_STR_NULL(GST_ELEMENT_NAME(GST_ELEMENT(element->gst))),
-                                               GST_STR_NULL(GST_ELEMENT_NAME(GST_ELEMENT_CAST(bin))));
+                                                       GST_STR_NULL(GST_ELEMENT_NAME(GST_ELEMENT(element->gst))),
+                                                       GST_STR_NULL(GST_ELEMENT_NAME(GST_ELEMENT_CAST(bin))));
 
                        successful_add_count++;
                }
@@ -864,13 +1094,13 @@ __mm_wfd_sink_gst_element_link_bucket(GList *element_bucket)
                if (element && element->gst) {
                        if (gst_element_link(GST_ELEMENT(prv_element->gst), GST_ELEMENT(element->gst))) {
                                wfd_sink_debug("linking [%s] to [%s] success",
-                                                       GST_STR_NULL(GST_ELEMENT_NAME(GST_ELEMENT(prv_element->gst))),
-                                                       GST_STR_NULL(GST_ELEMENT_NAME(GST_ELEMENT(element->gst))));
+                                                               GST_STR_NULL(GST_ELEMENT_NAME(GST_ELEMENT(prv_element->gst))),
+                                                               GST_STR_NULL(GST_ELEMENT_NAME(GST_ELEMENT(element->gst))));
                                successful_link_count++;
                        } else {
                                wfd_sink_error("linking [%s] to [%s] failed",
-                                                       GST_STR_NULL(GST_ELEMENT_NAME(GST_ELEMENT(prv_element->gst))),
-                                                       GST_STR_NULL(GST_ELEMENT_NAME(GST_ELEMENT(element->gst))));
+                                                               GST_STR_NULL(GST_ELEMENT_NAME(GST_ELEMENT(prv_element->gst))),
+                                                               GST_STR_NULL(GST_ELEMENT_NAME(GST_ELEMENT(element->gst))));
                                return -1;
                        }
                }
@@ -1019,8 +1249,8 @@ static int __mm_wfd_sink_set_state(mm_wfd_sink_t *wfd_sink, MMWFDSinkStateType s
 
        /* post state message to application */
        MMWFDSINK_POST_MESSAGE(wfd_sink,
-                                               MM_ERROR_NONE,
-                                               MMWFDSINK_CURRENT_STATE(wfd_sink));
+                                                       MM_ERROR_NONE,
+                                                       MMWFDSINK_CURRENT_STATE(wfd_sink));
 
        /* print state */
        MMWFDSINK_PRINT_STATE(wfd_sink);
@@ -1040,13 +1270,13 @@ __mm_wfd_sink_set_pipeline_state(mm_wfd_sink_t *wfd_sink, GstState state, gboole
        wfd_sink_debug_fenter();
 
        wfd_sink_return_val_if_fail(wfd_sink &&
-                                               wfd_sink->pipeline &&
-                                               wfd_sink->pipeline->mainbin &&
-                                               wfd_sink->pipeline->mainbin[WFD_SINK_M_PIPE].gst,
-                                               MM_ERROR_WFD_NOT_INITIALIZED);
+                                                               wfd_sink->pipeline &&
+                                                               wfd_sink->pipeline->mainbin &&
+                                                               wfd_sink->pipeline->mainbin[WFD_SINK_M_PIPE].gst,
+                                                               MM_ERROR_WFD_NOT_INITIALIZED);
 
        wfd_sink_return_val_if_fail(state > GST_STATE_VOID_PENDING,
-                               MM_ERROR_WFD_INVALID_ARGUMENT);
+                                                               MM_ERROR_WFD_INVALID_ARGUMENT);
 
        wfd_sink_debug("try to set %s state ", gst_element_state_get_name(state));
 
@@ -1060,7 +1290,7 @@ __mm_wfd_sink_set_pipeline_state(mm_wfd_sink_t *wfd_sink, GstState state, gboole
                wfd_sink_debug("wait for changing state is completed ");
 
                result = gst_element_get_state(wfd_sink->pipeline->mainbin[WFD_SINK_M_PIPE].gst,
-                                       &cur_state, &pending_state, wfd_sink->ini.state_change_timeout * GST_SECOND);
+                                                                               &cur_state, &pending_state, wfd_sink->ini.state_change_timeout * GST_SECOND);
                if (result == GST_STATE_CHANGE_FAILURE) {
                        wfd_sink_error("fail to get state within %d seconds....", wfd_sink->ini.state_change_timeout);
 
@@ -1072,8 +1302,8 @@ __mm_wfd_sink_set_pipeline_state(mm_wfd_sink_t *wfd_sink, GstState state, gboole
                }
 
                wfd_sink_debug("cur state is %s, pending state is %s",
-                                       gst_element_state_get_name(cur_state),
-                                       gst_element_state_get_name(pending_state));
+                                               gst_element_state_get_name(cur_state),
+                                               gst_element_state_get_name(pending_state));
        }
 
 
@@ -1091,9 +1321,9 @@ _mm_wfd_sink_reset_basetime(mm_wfd_sink_t *wfd_sink)
        wfd_sink_debug_fenter();
 
        wfd_sink_return_if_fail(wfd_sink &&
-                                       wfd_sink->pipeline &&
-                                       wfd_sink->pipeline->mainbin &&
-                                       wfd_sink->pipeline->mainbin[WFD_SINK_M_PIPE].gst);
+                                                       wfd_sink->pipeline &&
+                                                       wfd_sink->pipeline->mainbin &&
+                                                       wfd_sink->pipeline->mainbin[WFD_SINK_M_PIPE].gst);
        wfd_sink_return_if_fail(wfd_sink->need_to_reset_basetime);
 
 
@@ -1146,18 +1376,210 @@ _mm_wfd_sink_reset_basetime(mm_wfd_sink_t *wfd_sink)
 }
 
 int
+__mm_wfd_sink_unprepare_video_pipeline(mm_wfd_sink_t *wfd_sink)
+{
+       GstElement *pipeline  = NULL;
+       GstElement *v_decodebin  = NULL;
+       GstElement *v_sinkbin  = NULL;
+       GstPad *sinkpad = NULL;
+       GstPad *srcpad = NULL;
+       int ret = MM_ERROR_NONE;
+
+       wfd_sink_debug_fenter();
+
+       wfd_sink_return_val_if_fail(wfd_sink &&
+                                                               wfd_sink->pipeline,
+                                                               MM_ERROR_WFD_NOT_INITIALIZED);
+
+       PRINT_WFD_REF_COUNT(wfd_sink);
+       wfd_sink_error("No-error:unprepare video sink bin");
+       if (wfd_sink->pipeline->v_sinkbin && wfd_sink->pipeline->v_sinkbin[WFD_SINK_V_S_BIN].gst) {
+               v_sinkbin = wfd_sink->pipeline->v_sinkbin[WFD_SINK_V_S_BIN].gst;
+
+               if ((pipeline = GST_ELEMENT_CAST(gst_element_get_parent(v_sinkbin)))) {
+                       sinkpad = gst_element_get_static_pad(v_sinkbin, "sink");
+                       if (!sinkpad) {
+                               wfd_sink_error("failed to get sink pad from %s", GST_ELEMENT_NAME(v_sinkbin));
+                               goto ERROR;
+                       }
+
+                       if (gst_pad_is_linked(sinkpad)) {
+                               srcpad = gst_pad_get_peer(sinkpad);
+                               if (!srcpad) {
+                                       wfd_sink_error("failed to get peer pad of %s:%s",
+                                                                       GST_ELEMENT_NAME(GST_PAD_PARENT(sinkpad)), GST_PAD_NAME(sinkpad));
+                                       goto ERROR;
+                               }
+
+                               wfd_sink_debug("try to unlink %s:%s and %s:%s",
+                                                               GST_ELEMENT_NAME(GST_PAD_PARENT(srcpad)), GST_PAD_NAME(srcpad),
+                                                               GST_ELEMENT_NAME(GST_PAD_PARENT(sinkpad)), GST_PAD_NAME(sinkpad));
+                               if (!gst_pad_unlink(srcpad, sinkpad)) {
+                                       wfd_sink_error("failed to unlink %s:%s and %s:%s",
+                                                                       GST_ELEMENT_NAME(GST_PAD_PARENT(srcpad)), GST_PAD_NAME(srcpad),
+                                                                       GST_ELEMENT_NAME(GST_PAD_PARENT(sinkpad)), GST_PAD_NAME(sinkpad));
+                                       goto ERROR;
+                               }
+                               gst_object_unref(srcpad);
+                               srcpad = NULL;
+                       } else {
+                               wfd_sink_debug("video sinkbin's sinkpad is not linked, no need to unlink it");
+                       }
+                       gst_object_unref(sinkpad);
+                       sinkpad = NULL;
+
+                       gst_object_ref(v_sinkbin);
+                       if (!gst_bin_remove(GST_BIN(pipeline), GST_ELEMENT(v_sinkbin))) {
+                               wfd_sink_error("failed to remove %s from %s",
+                                                               GST_ELEMENT_NAME(v_sinkbin), GST_ELEMENT_NAME(pipeline));
+                               goto ERROR;
+                       }
+
+                       gst_object_unref(pipeline);
+                       pipeline = NULL;
+               }
+
+               ret = __mm_wfd_sink_destroy_video_sinkbin(wfd_sink);
+               if (ret != MM_ERROR_NONE) {
+                       wfd_sink_error("failed to destroy video sinkbin");
+                       goto ERROR;
+               }
+       }
+       PRINT_WFD_REF_COUNT(wfd_sink);
+
+       wfd_sink_error("No-error:unprepare video decode bin");
+       if (wfd_sink->pipeline->v_decodebin && wfd_sink->pipeline->v_decodebin[WFD_SINK_V_D_BIN].gst) {
+               v_decodebin = wfd_sink->pipeline->v_decodebin[WFD_SINK_V_D_BIN].gst;
+
+               if ((pipeline = GST_ELEMENT_CAST(gst_element_get_parent(v_decodebin)))) {
+                       sinkpad = gst_element_get_static_pad(v_decodebin, "sink");
+                       if (!sinkpad) {
+                               wfd_sink_error("failed to get sink pad from %s", GST_ELEMENT_NAME(v_decodebin));
+                               goto ERROR;
+                       }
+
+                       if (gst_pad_is_linked(sinkpad)) {
+                               srcpad = gst_pad_get_peer(sinkpad);
+                               if (!srcpad) {
+                                       wfd_sink_error("failed to get peer pad of %s:%s",
+                                                                       GST_ELEMENT_NAME(GST_PAD_PARENT(sinkpad)), GST_PAD_NAME(sinkpad));
+                                       goto ERROR;
+                               }
+
+                               wfd_sink_debug("try to unlink %s:%s and %s:%s",
+                                                               GST_ELEMENT_NAME(GST_PAD_PARENT(srcpad)), GST_PAD_NAME(srcpad),
+                                                               GST_ELEMENT_NAME(GST_PAD_PARENT(sinkpad)), GST_PAD_NAME(sinkpad));
+                               if (!gst_pad_unlink(srcpad, sinkpad)) {
+                                       wfd_sink_error("failed to unlink %s:%s and %s:%s",
+                                                                       GST_ELEMENT_NAME(GST_PAD_PARENT(srcpad)), GST_PAD_NAME(srcpad),
+                                                                       GST_ELEMENT_NAME(GST_PAD_PARENT(sinkpad)), GST_PAD_NAME(sinkpad));
+                                       goto ERROR;
+                               }
+                               gst_object_unref(srcpad);
+                               srcpad = NULL;
+                       } else {
+                               wfd_sink_debug("video decodebin's sinkpad is not linked, no need to unlink it");
+                       }
+                       gst_object_unref(sinkpad);
+                       sinkpad = NULL;
+
+                       srcpad = gst_element_get_static_pad(v_decodebin, "src");
+                       if (!srcpad) {
+                               wfd_sink_error("failed to get src pad from %s", GST_ELEMENT_NAME(v_decodebin));
+                               goto ERROR;
+                       }
+
+                       if (gst_pad_is_linked(srcpad)) {
+                               sinkpad = gst_pad_get_peer(srcpad);
+                               if (!sinkpad) {
+                                       wfd_sink_error("failed to get peer pad of %s:%s",
+                                                                       GST_ELEMENT_NAME(GST_PAD_PARENT(srcpad)), GST_PAD_NAME(srcpad));
+                                       goto ERROR;
+                               }
+
+                               wfd_sink_debug("try to unlink %s:%s and %s:%s",
+                                                               GST_ELEMENT_NAME(GST_PAD_PARENT(srcpad)), GST_PAD_NAME(srcpad),
+                                                               GST_ELEMENT_NAME(GST_PAD_PARENT(sinkpad)), GST_PAD_NAME(sinkpad));
+                               if (!gst_pad_unlink(srcpad, sinkpad)) {
+                                       wfd_sink_error("failed to unlink %s:%s and %s:%s",
+                                                                       GST_ELEMENT_NAME(GST_PAD_PARENT(srcpad)), GST_PAD_NAME(srcpad),
+                                                                       GST_ELEMENT_NAME(GST_PAD_PARENT(sinkpad)), GST_PAD_NAME(sinkpad));
+                                       goto ERROR;
+                               }
+                               gst_object_unref(sinkpad);
+                               sinkpad = NULL;
+                       } else {
+                               wfd_sink_debug("video decodebin's srcpad is not linked, no need to unlink it");
+                       }
+                       gst_object_unref(srcpad);
+                       srcpad = NULL;
+
+                       wfd_sink_error("try to remove %s from %s",
+                                                       GST_ELEMENT_NAME(v_decodebin), GST_ELEMENT_NAME(pipeline));
+                       gst_object_ref(v_decodebin);
+                       if (!gst_bin_remove(GST_BIN(pipeline), GST_ELEMENT(v_decodebin))) {
+                               wfd_sink_error("failed to remove %s from %s",
+                                                               GST_ELEMENT_NAME(v_decodebin), GST_ELEMENT_NAME(pipeline));
+                               goto ERROR;
+                       }
+
+                       gst_object_unref(pipeline);
+                       pipeline = NULL;
+               }
+
+               ret = __mm_wfd_sink_destroy_video_decodebin(wfd_sink);
+               if (ret != MM_ERROR_NONE) {
+                       wfd_sink_error("failed to destroy video decodebin");
+                       goto ERROR;
+               }
+       }
+       PRINT_WFD_REF_COUNT(wfd_sink);
+
+       wfd_sink_debug_fleave();
+
+       return ret;
+
+       /* ERRORS */
+ERROR:
+       if (pipeline) {
+               gst_object_unref(pipeline);
+               pipeline = NULL;
+       }
+
+       if (sinkpad) {
+               gst_object_unref(sinkpad);
+               sinkpad = NULL;
+       }
+
+       if (srcpad) {
+               gst_object_unref(srcpad);
+               srcpad = NULL;
+       }
+
+       /* need to notify to app */
+       MMWFDSINK_POST_MESSAGE(wfd_sink,
+                                                       MM_ERROR_WFD_INTERNAL,
+                                                       MMWFDSINK_CURRENT_STATE(wfd_sink));
+
+       return MM_ERROR_WFD_INTERNAL;
+}
+
+int
 __mm_wfd_sink_prepare_video_pipeline(mm_wfd_sink_t *wfd_sink, GstPad **pad)
 {
+       GstElement *pipeline  = NULL;
        GstElement *v_decodebin  = NULL;
        GstElement *v_sinkbin  = NULL;
+       GstPad *srcpad = NULL;
+       GstPad *sinkpad = NULL;
 
        wfd_sink_debug_fenter();
 
        wfd_sink_return_val_if_fail(wfd_sink &&
-                                               wfd_sink->pipeline &&
-                                               wfd_sink->pipeline->mainbin &&
-                                               wfd_sink->pipeline->mainbin[WFD_SINK_M_PIPE].gst,
-                                               MM_ERROR_WFD_NOT_INITIALIZED);
+                                                               wfd_sink->pipeline &&
+                                                               wfd_sink->pipeline->mainbin &&
+                                                               wfd_sink->pipeline->mainbin[WFD_SINK_M_PIPE].gst,
+                                                               MM_ERROR_WFD_NOT_INITIALIZED);
 
        /* check video decodebin is linked */
        if (!wfd_sink->video_decodebin_is_linked) {
@@ -1173,54 +1595,350 @@ __mm_wfd_sink_prepare_video_pipeline(mm_wfd_sink_t *wfd_sink, GstPad **pad)
                        wfd_sink_error("failed to link video decodebin.....");
                        goto ERROR;
                }
-       }
+       }
+
+       /* check video sinkbin is created */
+       if (wfd_sink->pipeline->v_sinkbin == NULL) {
+               if (MM_ERROR_NONE != __mm_wfd_sink_create_video_sinkbin(wfd_sink)) {
+                       wfd_sink_error("failed to create video sinkbin....");
+                       goto ERROR;
+               }
+       }
+       /* add video decodebin to pipeline */
+       if (wfd_sink->pipeline->v_decodebin && wfd_sink->pipeline->v_decodebin[WFD_SINK_V_D_BIN].gst) {
+               v_decodebin = wfd_sink->pipeline->v_decodebin[WFD_SINK_V_D_BIN].gst;
+
+               pipeline = GST_ELEMENT_CAST(gst_element_get_parent(v_decodebin));
+               if (!pipeline) {
+                       pipeline = wfd_sink->pipeline->mainbin[WFD_SINK_M_PIPE].gst;
+
+                       if (GST_STATE(v_decodebin) <= GST_STATE_NULL) {
+                               wfd_sink_debug("need to prepare %s", GST_ELEMENT_NAME(v_decodebin));
+                               if (GST_STATE_CHANGE_FAILURE == gst_element_set_state(v_decodebin, GST_STATE_READY)) {
+                                       wfd_sink_error("failed to set state(READY) to video decodebin");
+                                       goto ERROR;
+                               }
+                       }
+
+                       wfd_sink_debug("try to add %s to %s",
+                                                       GST_ELEMENT_NAME(v_decodebin), GST_ELEMENT_NAME(pipeline));
+                       if (!gst_bin_add(GST_BIN(pipeline), GST_ELEMENT(v_decodebin))) {
+                               wfd_sink_error("failed to add %s to %s",
+                                                               GST_ELEMENT_NAME(v_decodebin), GST_ELEMENT_NAME(pipeline));
+                               goto ERROR;
+                       }
+
+                       wfd_sink_debug("need to sync state %s with its parent", GST_ELEMENT_NAME(v_decodebin));
+                       if (!gst_element_sync_state_with_parent(GST_ELEMENT(v_decodebin))) {
+                               wfd_sink_error("failed to sync %s state with parent", GST_ELEMENT_NAME(v_decodebin));
+                               goto ERROR;
+                       }
+               } else {
+                       wfd_sink_debug("%s is already added to %s",
+                                                       GST_ELEMENT_NAME(v_decodebin), GST_ELEMENT_NAME(pipeline));
+                       gst_object_unref(pipeline);
+                       pipeline = NULL;
+               }
+       } else {
+               wfd_sink_warning("going on without video decodebin....");
+       }
+
+       /* add video sinkbin to pipeline */
+       if (wfd_sink->pipeline->v_sinkbin && wfd_sink->pipeline->v_sinkbin[WFD_SINK_V_S_BIN].gst) {
+               v_sinkbin = wfd_sink->pipeline->v_sinkbin[WFD_SINK_V_S_BIN].gst;
+
+               pipeline = GST_ELEMENT_CAST(gst_element_get_parent(v_sinkbin));
+               if (!pipeline) {
+                       pipeline = wfd_sink->pipeline->mainbin[WFD_SINK_M_PIPE].gst;
+
+                       /* prepare video sinkbin before adding */
+                       if (GST_STATE(v_sinkbin) <= GST_STATE_NULL) {
+                               wfd_sink_debug("need to prepare %s", GST_ELEMENT_NAME(v_sinkbin));
+                               if (GST_STATE_CHANGE_FAILURE == gst_element_set_state(v_sinkbin, GST_STATE_READY)) {
+                                       wfd_sink_error("failed to set state(READY) to video sinkbin");
+                                       goto ERROR;
+                               }
+                       }
+                       /* add video sinkbin to pipeline */
+                       wfd_sink_debug("try to  add %s to %s",
+                                                       GST_ELEMENT_NAME(v_sinkbin), GST_ELEMENT_NAME(pipeline));
+                       if (!gst_bin_add(GST_BIN(pipeline), GST_ELEMENT(v_sinkbin))) {
+                               wfd_sink_error("failed to add %s to %s",
+                                                               GST_ELEMENT_NAME(v_sinkbin), GST_ELEMENT_NAME(pipeline));
+                               goto ERROR;
+                       }
+
+                       /* sync state with parent */
+                       wfd_sink_debug("need to sync state %s with its parent", GST_ELEMENT_NAME(v_sinkbin));
+                       if (!gst_element_sync_state_with_parent(GST_ELEMENT(v_sinkbin))) {
+                               wfd_sink_error("failed to sync %s state with parent", GST_ELEMENT_NAME(v_sinkbin));
+                               goto ERROR;
+                       }
+               } else {
+                       wfd_sink_debug("%s is already added to %s",
+                                                       GST_ELEMENT_NAME(v_sinkbin), GST_ELEMENT_NAME(pipeline));
+                       gst_object_unref(pipeline);
+                       pipeline = NULL;
+               }
+       } else {
+               wfd_sink_warning("going on without video sinkbin....");
+       }
+
+
+       /* link video decodebin and sinkbin */
+       if (wfd_sink->pipeline->v_decodebin && wfd_sink->pipeline->v_decodebin[WFD_SINK_V_D_BIN].gst) {
+               v_decodebin = wfd_sink->pipeline->v_decodebin[WFD_SINK_V_D_BIN].gst;
+
+               if (pad)
+                       *pad = gst_element_get_static_pad(v_decodebin, "sink");
+
+               if (wfd_sink->pipeline->v_sinkbin && wfd_sink->pipeline->v_sinkbin[WFD_SINK_V_S_BIN].gst) {
+
+                       v_sinkbin = wfd_sink->pipeline->v_sinkbin[WFD_SINK_V_S_BIN].gst;
+
+                       srcpad = gst_element_get_static_pad(v_decodebin, "src");
+                       if (!srcpad) {
+                               wfd_sink_error("faied to get srcpad from %s", GST_ELEMENT_NAME(v_decodebin));
+                               goto ERROR;
+                       }
+
+                       if (!gst_pad_is_linked(srcpad)) {
+                               sinkpad = gst_element_get_static_pad(v_sinkbin, "sink");
+                               if (!sinkpad) {
+                                       wfd_sink_error("faied to get sinkpad from %s", GST_ELEMENT_NAME(v_sinkbin));
+                                       goto ERROR;
+                               }
+
+                               wfd_sink_debug("try to link %s:%s and %s:%s",
+                                                               GST_ELEMENT_NAME(GST_PAD_PARENT(srcpad)), GST_PAD_NAME(srcpad),
+                                                               GST_ELEMENT_NAME(GST_PAD_PARENT(sinkpad)), GST_PAD_NAME(sinkpad));
+                               if (GST_PAD_LINK_OK != gst_pad_link_full(srcpad, sinkpad, GST_PAD_LINK_CHECK_NOTHING)) {
+                                       wfd_sink_error("failed to link %s:%s and %s:%s",
+                                                                       GST_ELEMENT_NAME(GST_PAD_PARENT(srcpad)), GST_PAD_NAME(srcpad),
+                                                                       GST_ELEMENT_NAME(GST_PAD_PARENT(sinkpad)), GST_PAD_NAME(sinkpad));
+                                       goto ERROR;
+                               }
+                               gst_object_unref(sinkpad);
+                               sinkpad = NULL;
+                       }
+                       gst_object_unref(srcpad);
+                       srcpad = NULL;
+               }
+       } else if (wfd_sink->pipeline->v_sinkbin && wfd_sink->pipeline->v_sinkbin[WFD_SINK_V_S_BIN].gst) {
+               v_sinkbin = wfd_sink->pipeline->v_sinkbin[WFD_SINK_V_S_BIN].gst;
+               if (pad)
+                       *pad = gst_element_get_static_pad(v_sinkbin, "sink");
+       }
+
+       wfd_sink_debug_fleave();
+
+       return MM_ERROR_NONE;
+
+       /* ERRORS */
+ERROR:
+       if (sinkpad != NULL) {
+               gst_object_unref(sinkpad);
+               sinkpad = NULL;
+       }
+
+       if (srcpad != NULL) {
+               gst_object_unref(srcpad);
+               srcpad = NULL;
+       }
+
+       /* need to notify to app */
+       MMWFDSINK_POST_MESSAGE(wfd_sink,
+                                                       MM_ERROR_WFD_INTERNAL,
+                                                       MMWFDSINK_CURRENT_STATE(wfd_sink));
+
+       return MM_ERROR_WFD_INTERNAL;
+}
+
+int
+__mm_wfd_sink_unprepare_audio_pipeline(mm_wfd_sink_t *wfd_sink)
+{
+       GstElement *pipeline  = NULL;
+       GstElement *a_decodebin  = NULL;
+       GstElement *a_sinkbin  = NULL;
+       GstPad *sinkpad = NULL;
+       GstPad *srcpad = NULL;
+       int ret = MM_ERROR_NONE;
+
+       wfd_sink_debug_fenter();
+
+       wfd_sink_return_val_if_fail(wfd_sink &&
+                                                               wfd_sink->pipeline,
+                                                               MM_ERROR_WFD_NOT_INITIALIZED);
+
+       wfd_sink_error("No-error:unprepare audio sink bin");
+       PRINT_WFD_REF_COUNT(wfd_sink);
+
+       if (wfd_sink->pipeline->a_sinkbin && wfd_sink->pipeline->a_sinkbin[WFD_SINK_A_S_BIN].gst) {
+               a_sinkbin = wfd_sink->pipeline->a_sinkbin[WFD_SINK_A_S_BIN].gst;
+
+               if ((pipeline = GST_ELEMENT_CAST(gst_element_get_parent(a_sinkbin)))) {
+                       sinkpad = gst_element_get_static_pad(a_sinkbin, "sink");
+                       if (!sinkpad) {
+                               wfd_sink_error("failed to get sink pad from %s", GST_ELEMENT_NAME(a_sinkbin));
+                               goto ERROR;
+                       }
+
+                       if (gst_pad_is_linked(sinkpad)) {
+                               srcpad = gst_pad_get_peer(sinkpad);
+                               if (!srcpad) {
+                                       wfd_sink_error("failed to get peer pad of %s:%s",
+                                                                       GST_ELEMENT_NAME(GST_PAD_PARENT(sinkpad)), GST_PAD_NAME(sinkpad));
+                                       goto ERROR;
+                               }
+
+                               wfd_sink_debug("try to unlink %s:%s and %s:%s",
+                                                               GST_ELEMENT_NAME(GST_PAD_PARENT(srcpad)), GST_PAD_NAME(srcpad),
+                                                               GST_ELEMENT_NAME(GST_PAD_PARENT(sinkpad)), GST_PAD_NAME(sinkpad));
+                               if (!gst_pad_unlink(srcpad, sinkpad)) {
+                                       wfd_sink_error("failed to unlink %s:%s and %s:%s",
+                                                                       GST_ELEMENT_NAME(GST_PAD_PARENT(srcpad)), GST_PAD_NAME(srcpad),
+                                                                       GST_ELEMENT_NAME(GST_PAD_PARENT(sinkpad)), GST_PAD_NAME(sinkpad));
+                                       goto ERROR;
+                               }
+                               gst_object_unref(srcpad);
+                               srcpad = NULL;
+                       } else {
+                               wfd_sink_debug("audio sinkbin's sinkpad is not linked, no need to unlink it");
+                       }
+                       gst_object_unref(sinkpad);
+                       sinkpad = NULL;
+
+                       gst_object_ref(a_sinkbin);
+                       if (!gst_bin_remove(GST_BIN(pipeline), GST_ELEMENT(a_sinkbin))) {
+                               wfd_sink_error("failed to remove %s from %s",
+                                                               GST_ELEMENT_NAME(a_sinkbin), GST_ELEMENT_NAME(pipeline));
+                               goto ERROR;
+                       }
+
+                       gst_object_unref(pipeline);
+                       pipeline = NULL;
+               }
 
-       /* check video sinkbin is created */
-       if (wfd_sink->pipeline->v_sinkbin == NULL) {
-               if (MM_ERROR_NONE != __mm_wfd_sink_create_video_sinkbin(wfd_sink)) {
-                       wfd_sink_error("failed to create video sinkbin....");
+               ret = __mm_wfd_sink_destroy_audio_sinkbin(wfd_sink);
+               if (ret != MM_ERROR_NONE) {
+                       wfd_sink_error("failed to destroy audio sinkbin");
                        goto ERROR;
                }
        }
+       PRINT_WFD_REF_COUNT(wfd_sink);
 
-       /* set video decodebin state as READY */
-       if (wfd_sink->pipeline->v_decodebin && wfd_sink->pipeline->v_decodebin[WFD_SINK_V_D_BIN].gst) {
-               v_decodebin = wfd_sink->pipeline->v_decodebin[WFD_SINK_V_D_BIN].gst;
-               if (GST_STATE(v_decodebin) <= GST_STATE_NULL) {
-                       wfd_sink_debug("need to prepare %s", GST_ELEMENT_NAME(v_decodebin));
-                       if (GST_STATE_CHANGE_FAILURE == gst_element_set_state(v_decodebin, GST_STATE_READY)) {
-                               wfd_sink_error("failed to set state(READY) to video decodebin");
+       wfd_sink_error("No-error:unprepare audio decode bin");
+       if (wfd_sink->pipeline->a_decodebin && wfd_sink->pipeline->a_decodebin[WFD_SINK_A_D_BIN].gst) {
+               a_decodebin = wfd_sink->pipeline->a_decodebin[WFD_SINK_A_D_BIN].gst;
+
+               if ((pipeline = GST_ELEMENT_CAST(gst_element_get_parent(a_decodebin)))) {
+                       sinkpad = gst_element_get_static_pad(a_decodebin, "sink");
+                       if (!sinkpad) {
+                               wfd_sink_error("failed to get sink pad from %s", GST_ELEMENT_NAME(a_decodebin));
                                goto ERROR;
                        }
-               }
-       } else {
-               wfd_sink_warning("going on without video decodebin....");
-       }
 
-       /* set video sinkbin state as READY */
-       if (wfd_sink->pipeline->v_sinkbin && wfd_sink->pipeline->v_sinkbin[WFD_SINK_V_S_BIN].gst) {
-               v_sinkbin = wfd_sink->pipeline->v_sinkbin[WFD_SINK_V_S_BIN].gst;
-               if (GST_STATE(v_sinkbin) <= GST_STATE_NULL) {
-                       wfd_sink_debug("need to prepare %s", GST_ELEMENT_NAME(v_sinkbin));
-                       if (GST_STATE_CHANGE_FAILURE == gst_element_set_state(v_sinkbin, GST_STATE_READY)) {
-                               wfd_sink_error("failed to set state(READY) to video sinkbin");
+                       if (gst_pad_is_linked(sinkpad)) {
+                               srcpad = gst_pad_get_peer(sinkpad);
+                               if (!srcpad) {
+                                       wfd_sink_error("failed to get peer pad of %s:%s",
+                                                                       GST_ELEMENT_NAME(GST_PAD_PARENT(sinkpad)), GST_PAD_NAME(sinkpad));
+                                       goto ERROR;
+                               }
+
+                               wfd_sink_debug("try to unlink %s:%s and %s:%s",
+                                                               GST_ELEMENT_NAME(GST_PAD_PARENT(srcpad)), GST_PAD_NAME(srcpad),
+                                                               GST_ELEMENT_NAME(GST_PAD_PARENT(sinkpad)), GST_PAD_NAME(sinkpad));
+                               if (!gst_pad_unlink(srcpad, sinkpad)) {
+                                       wfd_sink_error("failed to unlink %s:%s and %s:%s",
+                                                                       GST_ELEMENT_NAME(GST_PAD_PARENT(srcpad)), GST_PAD_NAME(srcpad),
+                                                                       GST_ELEMENT_NAME(GST_PAD_PARENT(sinkpad)), GST_PAD_NAME(sinkpad));
+                                       goto ERROR;
+                               }
+                               gst_object_unref(srcpad);
+                               srcpad = NULL;
+                       } else {
+                               wfd_sink_debug("audio decodebin's sinkpad is not linked, no need to unlink it");
+                       }
+                       gst_object_unref(sinkpad);
+                       sinkpad = NULL;
+
+                       srcpad = gst_element_get_static_pad(a_decodebin, "src");
+                       if (!srcpad) {
+                               wfd_sink_error("failed to get src pad from %s", GST_ELEMENT_NAME(a_decodebin));
+                               goto ERROR;
+                       }
+
+                       if (gst_pad_is_linked(srcpad)) {
+                               sinkpad = gst_pad_get_peer(srcpad);
+                               if (!sinkpad) {
+                                       wfd_sink_error("failed to get peer pad of %s:%s",
+                                                                       GST_ELEMENT_NAME(GST_PAD_PARENT(srcpad)), GST_PAD_NAME(srcpad));
+                                       return MM_ERROR_WFD_INTERNAL;
+                               }
+
+                               wfd_sink_debug("try to unlink %s:%s and %s:%s",
+                                                               GST_ELEMENT_NAME(GST_PAD_PARENT(srcpad)), GST_PAD_NAME(srcpad),
+                                                               GST_ELEMENT_NAME(GST_PAD_PARENT(sinkpad)), GST_PAD_NAME(sinkpad));
+                               if (!gst_pad_unlink(srcpad, sinkpad)) {
+                                       wfd_sink_error("failed to unlink %s:%s and %s:%s",
+                                                                       GST_ELEMENT_NAME(GST_PAD_PARENT(srcpad)), GST_PAD_NAME(srcpad),
+                                                                       GST_ELEMENT_NAME(GST_PAD_PARENT(sinkpad)), GST_PAD_NAME(sinkpad));
+                                       return MM_ERROR_WFD_INTERNAL;
+                               }
+                               gst_object_unref(sinkpad);
+                               sinkpad = NULL;
+                       } else {
+                               wfd_sink_debug("audio decodebin's srcpad is not linked, no need to unlink it");
+                       }
+                       gst_object_unref(srcpad);
+                       srcpad = NULL;
+
+                       wfd_sink_error("try to remove %s from %s",
+                                                       GST_ELEMENT_NAME(a_decodebin), GST_ELEMENT_NAME(pipeline));
+                       gst_object_ref(a_decodebin);
+                       if (!gst_bin_remove(GST_BIN(pipeline), GST_ELEMENT(a_decodebin))) {
+                               wfd_sink_error("failed to remove %s from %s",
+                                                               GST_ELEMENT_NAME(a_decodebin), GST_ELEMENT_NAME(pipeline));
                                goto ERROR;
                        }
+
+                       gst_object_unref(pipeline);
+                       pipeline = NULL;
+               }
+
+               ret = __mm_wfd_sink_destroy_audio_decodebin(wfd_sink);
+               if (ret != MM_ERROR_NONE) {
+                       wfd_sink_error("failed to destroy audio decodebin");
+                       goto ERROR;
                }
-       } else {
-               wfd_sink_warning("going on without video sinkbin....");
        }
+       PRINT_WFD_REF_COUNT(wfd_sink);
 
        wfd_sink_debug_fleave();
 
-       return MM_ERROR_NONE;
+       return ret;
 
        /* ERRORS */
 ERROR:
+       if (pipeline) {
+               gst_object_unref(pipeline);
+               pipeline = NULL;
+       }
+       if (sinkpad) {
+               gst_object_unref(sinkpad);
+               sinkpad = NULL;
+       }
+
+       if (srcpad) {
+               gst_object_unref(srcpad);
+               srcpad = NULL;
+       }
+
        /* need to notify to app */
        MMWFDSINK_POST_MESSAGE(wfd_sink,
-                                               MM_ERROR_WFD_INTERNAL,
-                                               MMWFDSINK_CURRENT_STATE(wfd_sink));
+                                                       MM_ERROR_WFD_INTERNAL,
+                                                       MMWFDSINK_CURRENT_STATE(wfd_sink));
 
        return MM_ERROR_WFD_INTERNAL;
 }
@@ -1228,14 +1946,19 @@ ERROR:
 int
 __mm_wfd_sink_prepare_audio_pipeline(mm_wfd_sink_t *wfd_sink, GstPad **pad)
 {
+       GstElement *pipeline  = NULL;
        GstElement *a_decodebin  = NULL;
        GstElement *a_sinkbin  = NULL;
+       GstPad *srcpad = NULL;
+       GstPad *sinkpad = NULL;
 
        wfd_sink_debug_fenter();
 
        wfd_sink_return_val_if_fail(wfd_sink &&
-                                               wfd_sink->pipeline,
-                                               MM_ERROR_WFD_NOT_INITIALIZED);
+                                                               wfd_sink->pipeline &&
+                                                               wfd_sink->pipeline->mainbin &&
+                                                               wfd_sink->pipeline->mainbin[WFD_SINK_M_PIPE].gst,
+                                                               MM_ERROR_WFD_NOT_INITIALIZED);
 
        /* check audio decodebin is linked */
        if (!wfd_sink->audio_decodebin_is_linked) {
@@ -1261,44 +1984,159 @@ __mm_wfd_sink_prepare_audio_pipeline(mm_wfd_sink_t *wfd_sink, GstPad **pad)
                }
        }
 
-       /* set audio decodebin state as READY */
+       /* add audio decodebin to pipeline */
        if (wfd_sink->pipeline->a_decodebin && wfd_sink->pipeline->a_decodebin[WFD_SINK_A_D_BIN].gst) {
                a_decodebin = wfd_sink->pipeline->a_decodebin[WFD_SINK_A_D_BIN].gst;
-               if (GST_STATE(a_decodebin) <= GST_STATE_NULL) {
-                       wfd_sink_debug("need to prepare %s", GST_ELEMENT_NAME(a_decodebin));
-                       if (GST_STATE_CHANGE_FAILURE == gst_element_set_state(a_decodebin, GST_STATE_READY)) {
-                               wfd_sink_error("failed to set state(READY) to audio decodebin");
+
+               pipeline = GST_ELEMENT_CAST(gst_element_get_parent(a_decodebin));
+               if (!pipeline) {
+                       pipeline = wfd_sink->pipeline->mainbin[WFD_SINK_M_PIPE].gst;
+
+                       if (GST_STATE(a_decodebin) <= GST_STATE_NULL) {
+                               wfd_sink_debug("need to prepare %s", GST_ELEMENT_NAME(a_decodebin));
+                               if (GST_STATE_CHANGE_FAILURE == gst_element_set_state(a_decodebin, GST_STATE_READY)) {
+                                       wfd_sink_error("failed to set state(READY) to audio decodebin");
+                                       goto ERROR;
+                               }
+                       }
+
+                       wfd_sink_debug("try to add %s to %s",
+                                                       GST_ELEMENT_NAME(a_decodebin), GST_ELEMENT_NAME(pipeline));
+                       if (!gst_bin_add(GST_BIN(pipeline), GST_ELEMENT(a_decodebin))) {
+                               wfd_sink_error("failed to add %s to %s",
+                                                               GST_ELEMENT_NAME(a_decodebin), GST_ELEMENT_NAME(pipeline));
+                               goto ERROR;
+                       }
+
+                       wfd_sink_debug("need to sync state %s with its parent", GST_ELEMENT_NAME(a_decodebin));
+                       if (!gst_element_sync_state_with_parent(GST_ELEMENT(a_decodebin))) {
+                               wfd_sink_error("failed to sync %s state with parent", GST_ELEMENT_NAME(a_decodebin));
                                goto ERROR;
                        }
+               } else {
+                       wfd_sink_debug("%s is already added to %s",
+                                                       GST_ELEMENT_NAME(a_decodebin), GST_ELEMENT_NAME(pipeline));
+                       gst_object_unref(pipeline);
+                       pipeline = NULL;
                }
        } else {
                wfd_sink_warning("going on without audio decodebin....");
        }
 
-       /* set audio sinkbin state as READY */
+       /* add audio sinkbin to pipeline */
        if (wfd_sink->pipeline->a_sinkbin && wfd_sink->pipeline->a_sinkbin[WFD_SINK_A_S_BIN].gst) {
                a_sinkbin = wfd_sink->pipeline->a_sinkbin[WFD_SINK_A_S_BIN].gst;
-               if (GST_STATE(a_sinkbin) <= GST_STATE_NULL) {
-                       wfd_sink_debug("need to prepare %s", GST_ELEMENT_NAME(a_sinkbin));
-                       if (GST_STATE_CHANGE_FAILURE == gst_element_set_state(a_sinkbin , GST_STATE_READY)) {
-                               wfd_sink_error("failed to set state(READY) to audio sinkbin");
+
+               pipeline = GST_ELEMENT_CAST(gst_element_get_parent(a_sinkbin));
+               if (!pipeline) {
+                       pipeline = wfd_sink->pipeline->mainbin[WFD_SINK_M_PIPE].gst;
+
+                       /* prepare audio sinkbin before adding */
+                       if (GST_STATE(a_sinkbin) <= GST_STATE_NULL) {
+                               wfd_sink_debug("need to prepare %s", GST_ELEMENT_NAME(a_sinkbin));
+                               if (GST_STATE_CHANGE_FAILURE == gst_element_set_state(a_sinkbin, GST_STATE_READY)) {
+                                       wfd_sink_error("failed to set state(READY) to audio sinkbin");
+                                       goto ERROR;
+                               }
+                       }
+
+                       /* add audio sinkbin to pipeline */
+                       wfd_sink_debug("try to  add %s to %s",
+                                                       GST_ELEMENT_NAME(a_sinkbin), GST_ELEMENT_NAME(pipeline));
+                       if (!gst_bin_add(GST_BIN(pipeline), GST_ELEMENT(a_sinkbin))) {
+                               wfd_sink_error("failed to add %s to %s",
+                                                               GST_ELEMENT_NAME(a_sinkbin), GST_ELEMENT_NAME(pipeline));
+                               goto ERROR;
+                       }
+
+                       /* sync state with parent */
+                       wfd_sink_debug("need to sync state %s with its parent", GST_ELEMENT_NAME(a_sinkbin));
+                       if (!gst_element_sync_state_with_parent(GST_ELEMENT(a_sinkbin))) {
+                               wfd_sink_error("failed to sync %s state with parent", GST_ELEMENT_NAME(a_sinkbin));
                                goto ERROR;
                        }
+               } else {
+                       wfd_sink_debug("%s is already added to %s",
+                                                       GST_ELEMENT_NAME(a_sinkbin), GST_ELEMENT_NAME(pipeline));
+                       gst_object_unref(pipeline);
+                       pipeline = NULL;
                }
        } else {
                wfd_sink_warning("going on without audio sinkbin....");
        }
 
+
+       /* link audio decodebin and sinkbin */
+       if (wfd_sink->pipeline->a_decodebin && wfd_sink->pipeline->a_decodebin[WFD_SINK_A_D_BIN].gst) {
+               a_decodebin = wfd_sink->pipeline->a_decodebin[WFD_SINK_A_D_BIN].gst;
+
+               if (pad)
+                       *pad = gst_element_get_static_pad(a_decodebin, "sink");
+
+               if (wfd_sink->pipeline->a_sinkbin && wfd_sink->pipeline->a_sinkbin[WFD_SINK_A_S_BIN].gst) {
+
+                       a_sinkbin = wfd_sink->pipeline->a_sinkbin[WFD_SINK_A_S_BIN].gst;
+
+                       srcpad = gst_element_get_static_pad(a_decodebin, "src");
+                       if (!srcpad) {
+                               wfd_sink_error("faied to get srcpad from %s", GST_ELEMENT_NAME(a_decodebin));
+                               goto ERROR;
+                       }
+
+                       if (!gst_pad_is_linked(srcpad)) {
+                               sinkpad = gst_element_get_static_pad(a_sinkbin, "sink");
+                               if (!sinkpad) {
+                                       wfd_sink_error("faied to get sinkpad from %s", GST_ELEMENT_NAME(a_sinkbin));
+                                       goto ERROR;
+                               }
+
+                               wfd_sink_debug("try to link %s:%s and %s:%s",
+                                                               GST_ELEMENT_NAME(GST_PAD_PARENT(srcpad)), GST_PAD_NAME(srcpad),
+                                                               GST_ELEMENT_NAME(GST_PAD_PARENT(sinkpad)), GST_PAD_NAME(sinkpad));
+                               if (GST_PAD_LINK_OK != gst_pad_link_full(srcpad, sinkpad, GST_PAD_LINK_CHECK_NOTHING)) {
+                                       wfd_sink_error("failed to link %s:%s and %s:%s",
+                                                                       GST_ELEMENT_NAME(GST_PAD_PARENT(srcpad)), GST_PAD_NAME(srcpad),
+                                                                       GST_ELEMENT_NAME(GST_PAD_PARENT(sinkpad)), GST_PAD_NAME(sinkpad));
+
+                                       goto ERROR;
+                               }
+                               gst_object_unref(sinkpad);
+                               sinkpad = NULL;
+                       }
+                       gst_object_unref(srcpad);
+                       srcpad = NULL;
+               }
+       } else if (wfd_sink->pipeline->a_sinkbin && wfd_sink->pipeline->a_sinkbin[WFD_SINK_A_S_BIN].gst) {
+               a_sinkbin = wfd_sink->pipeline->a_sinkbin[WFD_SINK_A_S_BIN].gst;
+               if (pad)
+                       *pad = gst_element_get_static_pad(a_sinkbin, "sink");
+       }
+
        wfd_sink_debug_fleave();
 
        return MM_ERROR_NONE;
 
        /* ERRORS */
 ERROR:
+       if (pipeline) {
+               gst_object_unref(pipeline);
+               pipeline = NULL;
+       }
+
+       if (sinkpad) {
+               gst_object_unref(sinkpad);
+               sinkpad = NULL;
+       }
+
+       if (srcpad) {
+               gst_object_unref(srcpad);
+               srcpad = NULL;
+       }
+
        /* need to notify to app */
        MMWFDSINK_POST_MESSAGE(wfd_sink,
-                                               MM_ERROR_WFD_INTERNAL,
-                                               MMWFDSINK_CURRENT_STATE(wfd_sink));
+                                                       MM_ERROR_WFD_INTERNAL,
+                                                       MMWFDSINK_CURRENT_STATE(wfd_sink));
 
        return MM_ERROR_WFD_INTERNAL;
 }
@@ -1321,10 +2159,10 @@ _mm_wfd_sink_check_running_time(GstPad *pad, GstPadProbeInfo *info, gpointer u_d
 
        wfd_sink_return_val_if_fail(info, FALSE);
        wfd_sink_return_val_if_fail(wfd_sink &&
-                                               wfd_sink->pipeline &&
-                                               wfd_sink->pipeline->mainbin &&
-                                               wfd_sink->pipeline->mainbin[WFD_SINK_M_PIPE].gst,
-                                               GST_PAD_PROBE_DROP);
+                                                               wfd_sink->pipeline &&
+                                                               wfd_sink->pipeline->mainbin &&
+                                                               wfd_sink->pipeline->mainbin[WFD_SINK_M_PIPE].gst,
+                                                               GST_PAD_PROBE_DROP);
 
        if (!wfd_sink->clock) {
                wfd_sink_warning("pipeline did not select clock, yet");
@@ -1347,8 +2185,8 @@ _mm_wfd_sink_check_running_time(GstPad *pad, GstPadProbeInfo *info, gpointer u_d
                running_time = current_time - (start_time + base_time);
        } else {
                wfd_sink_debug("current time %"GST_TIME_FORMAT", start time %"GST_TIME_FORMAT
-                                       "  base time %"GST_TIME_FORMAT"", GST_TIME_ARGS(current_time),
-                                       GST_TIME_ARGS(start_time), GST_TIME_ARGS(base_time));
+                                               "  base time %"GST_TIME_FORMAT"", GST_TIME_ARGS(current_time),
+                                               GST_TIME_ARGS(start_time), GST_TIME_ARGS(base_time));
                return GST_PAD_PROBE_OK;
        }
 
@@ -1376,8 +2214,8 @@ _mm_wfd_sink_check_running_time(GstPad *pad, GstPadProbeInfo *info, gpointer u_d
                if (diff < 0) {
                        /* this buffer could be NOT rendered */
                        wfd_sink_debug("%s : diff time : -%" GST_TIME_FORMAT "",
-                                               GST_STR_NULL((GST_OBJECT_NAME(pad))),
-                                               GST_TIME_ARGS(GST_CLOCK_DIFF(render_time, running_time)));
+                                                       GST_STR_NULL((GST_OBJECT_NAME(pad))),
+                                                       GST_TIME_ARGS(GST_CLOCK_DIFF(render_time, running_time)));
                } else {
                        /* this buffer could be rendered */
                        /*wfd_sink_debug ("%s :diff time : %" GST_TIME_FORMAT "", */
@@ -1433,9 +2271,9 @@ _mm_wfd_sink_check_running_time(GstPad *pad, GstPadProbeInfo *info, gpointer u_d
                                }
                        } else {
                                wfd_sink_debug("there is no video buffer flow during %"GST_TIME_FORMAT
-                                                       " ~ %" GST_TIME_FORMAT"",
-                                                       GST_TIME_ARGS(wfd_sink->last_buffer_timestamp),
-                                                       GST_TIME_ARGS(GST_BUFFER_TIMESTAMP(buffer)));
+                                                               " ~ %" GST_TIME_FORMAT"",
+                                                               GST_TIME_ARGS(wfd_sink->last_buffer_timestamp),
+                                                               GST_TIME_ARGS(GST_BUFFER_TIMESTAMP(buffer)));
                        }
 
                        /* check audio */
@@ -1456,9 +2294,9 @@ _mm_wfd_sink_check_running_time(GstPad *pad, GstPadProbeInfo *info, gpointer u_d
                                }
                        } else {
                                wfd_sink_debug("there is no audio buffer flow during %"GST_TIME_FORMAT
-                                                       " ~ %" GST_TIME_FORMAT"",
-                                                       GST_TIME_ARGS(wfd_sink->last_buffer_timestamp),
-                                                       GST_TIME_ARGS(GST_BUFFER_TIMESTAMP(buffer)));
+                                                               " ~ %" GST_TIME_FORMAT"",
+                                                               GST_TIME_ARGS(wfd_sink->last_buffer_timestamp),
+                                                               GST_TIME_ARGS(GST_BUFFER_TIMESTAMP(buffer)));
                        }
 
                        /* selecet average_gap_diff between video and audio */
@@ -1492,8 +2330,8 @@ _mm_wfd_sink_check_running_time(GstPad *pad, GstPadProbeInfo *info, gpointer u_d
                        }
 
                        wfd_sink_debug("average diff gap difference beween audio:%s%lld and video:%s%lld ",
-                                               audio_minus_compensation ? "-" : "", audio_avgrage_gap_diff,
-                                               video_minus_compensation ? "-" : "", video_avgrage_gap_diff);
+                                                       audio_minus_compensation ? "-" : "", audio_avgrage_gap_diff,
+                                                       video_minus_compensation ? "-" : "", video_avgrage_gap_diff);
 
 
                        /* if calculated gap diff is larger than 1ms. need to compensate buffer timestamp */
@@ -1504,9 +2342,9 @@ _mm_wfd_sink_check_running_time(GstPad *pad, GstPadProbeInfo *info, gpointer u_d
                                        ts_offset += avgrage_gap_diff;
 
                                wfd_sink_debug("do timestamp compensation : %s%lld (ts-offset : %"
-                                               GST_TIME_FORMAT") at(%" GST_TIME_FORMAT")",
-                                               minus_compensation ? "-" : "", avgrage_gap_diff,
-                                               GST_TIME_ARGS(ts_offset), GST_TIME_ARGS(running_time));
+                                                               GST_TIME_FORMAT") at(%" GST_TIME_FORMAT")",
+                                                               minus_compensation ? "-" : "", avgrage_gap_diff,
+                                                               GST_TIME_ARGS(ts_offset), GST_TIME_ARGS(running_time));
 
                                if (wfd_sink->pipeline && wfd_sink->pipeline->a_sinkbin && wfd_sink->pipeline->a_sinkbin[WFD_SINK_A_S_SINK].gst)
                                        g_object_set(G_OBJECT(wfd_sink->pipeline->a_sinkbin[WFD_SINK_A_S_SINK].gst), "ts-offset", (gint64)ts_offset, NULL);
@@ -1514,7 +2352,7 @@ _mm_wfd_sink_check_running_time(GstPad *pad, GstPadProbeInfo *info, gpointer u_d
                                        g_object_set(G_OBJECT(wfd_sink->pipeline->v_sinkbin[WFD_SINK_V_S_SINK].gst), "ts-offset", (gint64)ts_offset, NULL);
                        } else {
                                wfd_sink_debug("don't need to do timestamp compensation : %s%lld (ts-offset : %"GST_TIME_FORMAT ")",
-                                               minus_compensation ? "-" : "", avgrage_gap_diff, GST_TIME_ARGS(ts_offset));
+                                                               minus_compensation ? "-" : "", avgrage_gap_diff, GST_TIME_ARGS(ts_offset));
                        }
 
                        /* reset values*/
@@ -1526,7 +2364,7 @@ _mm_wfd_sink_check_running_time(GstPad *pad, GstPadProbeInfo *info, gpointer u_d
                }
        } else {
                wfd_sink_debug("first update last buffer timestamp :%" GST_TIME_FORMAT,
-                                       GST_TIME_ARGS(GST_BUFFER_TIMESTAMP(buffer)));
+                                               GST_TIME_ARGS(GST_BUFFER_TIMESTAMP(buffer)));
                wfd_sink->last_buffer_timestamp = GST_BUFFER_TIMESTAMP(buffer);
        }
 
@@ -1535,92 +2373,59 @@ _mm_wfd_sink_check_running_time(GstPad *pad, GstPadProbeInfo *info, gpointer u_d
 
 
 static void
-__mm_wfd_sink_demux_pad_added(GstElement *ele, GstPad *pad, gpointer data)
+__mm_wfd_sink_demux_pad_added(GstElement *demux, GstPad *pad, gpointer data)
 {
        mm_wfd_sink_t *wfd_sink = (mm_wfd_sink_t *)data;
        gchar *name = gst_pad_get_name(pad);
        GstElement *pipeline = NULL;
-       GstElement *decodebin = NULL;
-       GstElement *sinkbin = NULL;
+       GstElement *valve = NULL;
        GstPad *sinkpad = NULL;
        GstPad *srcpad = NULL;
 
        wfd_sink_debug_fenter();
 
        wfd_sink_return_if_fail(wfd_sink &&
-                                       wfd_sink->pipeline &&
-                                       wfd_sink->pipeline->mainbin &&
-                                       wfd_sink->pipeline->mainbin[WFD_SINK_M_PIPE].gst);
+                                                       wfd_sink->pipeline &&
+                                                       wfd_sink->pipeline->mainbin &&
+                                                       wfd_sink->pipeline->mainbin[WFD_SINK_M_PIPE].gst);
 
        pipeline = wfd_sink->pipeline->mainbin[WFD_SINK_M_PIPE].gst;
 
-       /* take decodebin/sinkbin */
-       if (name[0] == 'v') {
-               wfd_sink_debug("=========== >>>>>>>>>> Received VIDEO pad...");
-
-               MMWFDSINK_PAD_PROBE(wfd_sink, pad, NULL,  NULL);
-
-               gst_pad_add_probe(pad,
-                                       GST_PAD_PROBE_TYPE_BUFFER,
-                                       _mm_wfd_sink_check_running_time,
-                                       (gpointer)wfd_sink,
-                                       NULL);
-
-               if (MM_ERROR_NONE != __mm_wfd_sink_prepare_video_pipeline(wfd_sink, &sinkpad)) {
-                       wfd_sink_error("failed to prepare video pipeline....");
-                       goto ERROR;
-               }
+       /* take srcpad from demuxer added pad */
+       srcpad = gst_object_ref(pad);
 
-               if (wfd_sink->pipeline->v_decodebin && wfd_sink->pipeline->v_decodebin[WFD_SINK_V_D_BIN].gst)
-                       decodebin = wfd_sink->pipeline->v_decodebin[WFD_SINK_V_D_BIN].gst;
-               if (wfd_sink->pipeline->v_sinkbin && wfd_sink->pipeline->v_sinkbin[WFD_SINK_V_S_BIN].gst)
-                       sinkbin = wfd_sink->pipeline->v_sinkbin[WFD_SINK_V_S_BIN].gst;
+       if (name[0] == 'v') {
+               if (wfd_sink->pipeline->mainbin[WFD_SINK_M_V_VALVE].gst)
+                       valve = wfd_sink->pipeline->mainbin[WFD_SINK_M_V_VALVE].gst;
        } else if (name[0] == 'a') {
-               wfd_sink_debug("=========== >>>>>>>>>> Received AUDIO pad...");
-
-               MMWFDSINK_PAD_PROBE(wfd_sink, pad, NULL,  NULL);
-
-               gst_pad_add_probe(pad,
-                                       GST_PAD_PROBE_TYPE_BUFFER,
-                                       _mm_wfd_sink_check_running_time,
-                                       (gpointer)wfd_sink,
-                                       NULL);
-
-               if (MM_ERROR_NONE != __mm_wfd_sink_prepare_audio_pipeline(wfd_sink, &sinkpad)) {
-                       wfd_sink_error("failed to prepare audio pipeline....");
-                       goto ERROR;
-               }
-
-               if (wfd_sink->pipeline->a_decodebin && wfd_sink->pipeline->a_decodebin[WFD_SINK_A_D_BIN].gst)
-                       decodebin = wfd_sink->pipeline->a_decodebin[WFD_SINK_A_D_BIN].gst;
-               if (wfd_sink->pipeline->a_sinkbin && wfd_sink->pipeline->a_sinkbin[WFD_SINK_A_S_BIN].gst)
-                       sinkbin = wfd_sink->pipeline->a_sinkbin[WFD_SINK_A_S_BIN].gst;
-       } else {
-               wfd_sink_error("unexceptable pad is added!!!");
-               return;
+               if (wfd_sink->pipeline->mainbin[WFD_SINK_M_A_VALVE].gst)
+                       valve = wfd_sink->pipeline->mainbin[WFD_SINK_M_A_VALVE].gst;
        }
 
-       srcpad = gst_object_ref(pad);
+       /* add, link and run the valve */
+       if (valve) {
+               wfd_sink_debug("try to add %s to pipeline", GST_ELEMENT_NAME(valve));
 
-       /* add decodebin and link */
-       if (decodebin) {
-               if (!gst_bin_add(GST_BIN(pipeline), decodebin)) {
+               if (!gst_bin_add(GST_BIN(pipeline), valve)) {
                        wfd_sink_error("failed to add %s to pipeline",
-                                       GST_STR_NULL(GST_ELEMENT_NAME(decodebin)));
+                                                       GST_ELEMENT_NAME(valve));
                        goto ERROR;
                }
 
-               sinkpad = gst_element_get_static_pad(decodebin, "sink");
+               sinkpad = gst_element_get_static_pad(valve, "sink");
                if (!sinkpad) {
-                       wfd_sink_error("failed to get sink pad from %s",
-                                       GST_STR_NULL(GST_ELEMENT_NAME(decodebin)));
+                               wfd_sink_error("failed to get sink pad from %s",
+                                                               GST_ELEMENT_NAME(valve));
                        goto ERROR;
                }
 
-               if (GST_PAD_LINK_OK != gst_pad_link(srcpad, sinkpad)) {
-                       wfd_sink_error("failed to link %s and %s",
-                                       GST_STR_NULL(GST_PAD_NAME(srcpad)),
-                                       GST_STR_NULL(GST_PAD_NAME(sinkpad)));
+               wfd_sink_debug("try to link %s:%s and %s:%s",
+                                               GST_ELEMENT_NAME(GST_PAD_PARENT(srcpad)), GST_PAD_NAME(srcpad),
+                                               GST_ELEMENT_NAME(GST_PAD_PARENT(sinkpad)), GST_PAD_NAME(sinkpad));
+               if (GST_PAD_LINK_OK != gst_pad_link_full(srcpad, sinkpad, GST_PAD_LINK_CHECK_NOTHING)) {
+                       wfd_sink_error("failed to link %s:%s and %s:%s",
+                                                       GST_ELEMENT_NAME(GST_PAD_PARENT(srcpad)), GST_PAD_NAME(srcpad),
+                                                       GST_ELEMENT_NAME(GST_PAD_PARENT(sinkpad)), GST_PAD_NAME(sinkpad));
                        goto ERROR;
                }
                gst_object_unref(GST_OBJECT(srcpad));
@@ -1628,62 +2433,66 @@ __mm_wfd_sink_demux_pad_added(GstElement *ele, GstPad *pad, gpointer data)
                gst_object_unref(GST_OBJECT(sinkpad));
                sinkpad = NULL;
 
-               srcpad = gst_element_get_static_pad(decodebin, "src");
+               wfd_sink_debug("try to sync %s's state with parent", GST_ELEMENT_NAME(valve));
+               if (!gst_element_sync_state_with_parent(GST_ELEMENT_CAST(valve))) {
+                       wfd_sink_error("failed to sync %s state with parent",
+                                                       GST_PAD_NAME(valve));
+                       goto ERROR;
+               }
+
+               srcpad = gst_element_get_static_pad(valve, "src");
                if (!srcpad) {
                        wfd_sink_error("failed to get src pad from %s",
-                                       GST_STR_NULL(GST_ELEMENT_NAME(decodebin)));
+                                                       GST_ELEMENT_NAME(valve));
                        goto ERROR;
                }
-       } else {
-               wfd_sink_warning("going on without decodebin...");
        }
 
-       /* add sinkbin and link */
-       if (sinkbin) {
-               if (!gst_bin_add(GST_BIN(pipeline), sinkbin)) {
-                       wfd_sink_error("failed to add %s to pipeline",
-                                       GST_STR_NULL(GST_ELEMENT_NAME(sinkbin)));
-                       goto ERROR;
-               }
+       /* take decodebin/sinkbin */
+       if (name[0] == 'v') {
+               wfd_sink_debug("=========== >>>>>>>>>> Received VIDEO pad...");
 
-               sinkpad = gst_element_get_static_pad(sinkbin, "sink");
-               if (!sinkpad) {
-                       wfd_sink_error("failed to get sink pad from %s",
-                                       GST_STR_NULL(GST_ELEMENT_NAME(sinkbin)));
-                       goto ERROR;
-               }
+               MMWFDSINK_PAD_PROBE(wfd_sink, pad, NULL,  NULL);
 
-               if (GST_PAD_LINK_OK != gst_pad_link(srcpad, sinkpad)) {
-                       wfd_sink_error("failed to link %s and %s",
-                                       GST_STR_NULL(GST_PAD_NAME(srcpad)),
-                                       GST_STR_NULL(GST_PAD_NAME(sinkpad)));
+               gst_pad_add_probe(pad,
+                                               GST_PAD_PROBE_TYPE_BUFFER,
+                                               _mm_wfd_sink_check_running_time,
+                                               (gpointer)wfd_sink,
+                                               NULL);
+
+               if (MM_ERROR_NONE != __mm_wfd_sink_prepare_video_pipeline(wfd_sink, &sinkpad)) {
+                       wfd_sink_error("failed to prepare video pipeline....");
                        goto ERROR;
                }
-               gst_object_unref(GST_OBJECT(srcpad));
-               srcpad = NULL;
-               gst_object_unref(GST_OBJECT(sinkpad));
-               sinkpad = NULL;
-       } else {
-               wfd_sink_error("there is no sinkbin...");
-               goto ERROR;
-       }
+       } else if (name[0] == 'a') {
+               wfd_sink_debug("=========== >>>>>>>>>> Received AUDIO pad...");
 
+               MMWFDSINK_PAD_PROBE(wfd_sink, pad, NULL,  NULL);
 
-       /* run */
-       if (decodebin) {
-               if (!gst_element_sync_state_with_parent(GST_ELEMENT_CAST(decodebin))) {
-                       wfd_sink_error("failed to sync %s state with parent",
-                               GST_STR_NULL(GST_PAD_NAME(decodebin)));
+               gst_pad_add_probe(pad,
+                                               GST_PAD_PROBE_TYPE_BUFFER,
+                                               _mm_wfd_sink_check_running_time,
+                                               (gpointer)wfd_sink,
+                                               NULL);
+
+               if (MM_ERROR_NONE != __mm_wfd_sink_prepare_audio_pipeline(wfd_sink, &sinkpad)) {
+                       wfd_sink_error("failed to prepare audio pipeline....");
                        goto ERROR;
                }
+       } else {
+               wfd_sink_error("unexceptable pad is added!!!");
+               goto ERROR;
        }
 
-       if (sinkbin) {
-               if (!gst_element_sync_state_with_parent(GST_ELEMENT_CAST(sinkbin))) {
-                       wfd_sink_error("failed to sync %s state with parent",
-                               GST_STR_NULL(GST_PAD_NAME(sinkbin)));
-                       goto ERROR;
-               }
+       /* link */
+       wfd_sink_debug("try to link %s:%s and %s:%s",
+                                       GST_ELEMENT_NAME(GST_PAD_PARENT(srcpad)), GST_PAD_NAME(srcpad),
+                                       GST_ELEMENT_NAME(GST_PAD_PARENT(sinkpad)), GST_PAD_NAME(sinkpad));
+       if (GST_PAD_LINK_OK != gst_pad_link_full(srcpad, sinkpad, GST_PAD_LINK_CHECK_NOTHING)) {
+               wfd_sink_error("failed to link %s:%s and %s:%s",
+                                               GST_ELEMENT_NAME(GST_PAD_PARENT(srcpad)), GST_PAD_NAME(srcpad),
+                                               GST_ELEMENT_NAME(GST_PAD_PARENT(sinkpad)), GST_PAD_NAME(sinkpad));
+               goto ERROR;
        }
 
        if (name[0] == 'v') {
@@ -1747,8 +2556,6 @@ __mm_wfd_sink_update_stream_info(GstElement *wfdsrc, GstStructure *str, gpointer
        MMWFDSinkStreamInfo *stream_info = NULL;
        gint is_valid_audio_format = FALSE;
        gint is_valid_video_format = FALSE;
-       gint audio_codec = MM_WFD_SINK_AUDIO_CODEC_NONE;
-       gint video_codec = MM_WFD_SINK_VIDEO_CODEC_NONE;
        gchar *audio_format;
        gchar *video_format;
 
@@ -1759,9 +2566,6 @@ __mm_wfd_sink_update_stream_info(GstElement *wfdsrc, GstStructure *str, gpointer
 
        stream_info = &wfd_sink->stream_info;
 
-       audio_codec = wfd_sink->stream_info.audio_stream_info.codec;
-       video_codec = wfd_sink->stream_info.video_stream_info.codec;
-
        if (gst_structure_has_field(str, "audio_format")) {
                is_valid_audio_format = TRUE;
                audio_format = g_strdup(gst_structure_get_string(str, "audio_format"));
@@ -1784,18 +2588,13 @@ __mm_wfd_sink_update_stream_info(GstElement *wfdsrc, GstStructure *str, gpointer
                        if (gst_structure_has_field(str, "audio_bitwidth"))
                                gst_structure_get_int(str, "audio_bitwidth", &stream_info->audio_stream_info.bitwidth);
 
-                       if (audio_codec != MM_WFD_SINK_AUDIO_CODEC_NONE) {
-                               if (audio_codec != stream_info->audio_stream_info.codec)
-                                       wfd_sink_debug("audio codec is changed...need to change audio decodebin");
-                       } else {
-                               WFD_SINK_MANAGER_APPEND_CMD(wfd_sink, WFD_SINK_MANAGER_CMD_PREPARE_A_PIPELINE);
-                       }
+                       WFD_SINK_MANAGER_APPEND_CMD(wfd_sink, WFD_SINK_MANAGER_CMD_PREPARE_A_PIPELINE);
 
                        wfd_sink_debug("audio_format : %s \n \t rate :  %d \n \t channels :  %d \n \t bitwidth :  %d \n \t      \n",
-                                               audio_format,
-                                               stream_info->audio_stream_info.sample_rate,
-                                               stream_info->audio_stream_info.channels,
-                                               stream_info->audio_stream_info.bitwidth);
+                                                       audio_format,
+                                                       stream_info->audio_stream_info.sample_rate,
+                                                       stream_info->audio_stream_info.channels,
+                                                       stream_info->audio_stream_info.bitwidth);
                }
        }
 
@@ -1819,18 +2618,13 @@ __mm_wfd_sink_update_stream_info(GstElement *wfdsrc, GstStructure *str, gpointer
                        if (gst_structure_has_field(str, "video_framerate"))
                                gst_structure_get_int(str, "video_framerate", &stream_info->video_stream_info.frame_rate);
 
-                       if (video_codec != MM_WFD_SINK_AUDIO_CODEC_NONE) {
-                               if (video_codec != stream_info->video_stream_info.codec)
-                                       wfd_sink_debug("video codec is changed...need to change video decodebin");
-                       } else {
-                               WFD_SINK_MANAGER_APPEND_CMD(wfd_sink, WFD_SINK_MANAGER_CMD_PREPARE_V_PIPELINE);
-                       }
+                       WFD_SINK_MANAGER_APPEND_CMD(wfd_sink, WFD_SINK_MANAGER_CMD_PREPARE_V_PIPELINE);
 
                        wfd_sink_debug("video_format : %s \n \t width :  %d \n \t height :  %d \n \t frame_rate :  %d \n \t",
-                                               video_format,
-                                               stream_info->video_stream_info.width,
-                                               stream_info->video_stream_info.height,
-                                               stream_info->video_stream_info.frame_rate);
+                                                       video_format,
+                                                       stream_info->video_stream_info.width,
+                                                       stream_info->video_stream_info.height,
+                                                       stream_info->video_stream_info.frame_rate);
                }
        }
 
@@ -1840,7 +2634,7 @@ __mm_wfd_sink_update_stream_info(GstElement *wfdsrc, GstStructure *str, gpointer
 }
 
 static void __mm_wfd_sink_prepare_video_resolution(gint resolution, guint64 *CEA_resolution,
-                                                       guint64 *VESA_resolution, guint64 *HH_resolution)
+                                                                                                       guint64 *VESA_resolution, guint64 *HH_resolution)
 {
        if (resolution == MM_WFD_SINK_RESOLUTION_UNKNOWN) return;
 
@@ -1909,11 +2703,11 @@ static int __mm_wfd_sink_prepare_source(mm_wfd_sink_t *wfd_sink, GstElement *wfd
 
        /* set audio parameter for Wi-Fi Display session negotiation */
        wfd_audio_codecs = gst_structure_new("wfd_audio_codecs",
-                                       "audio_codec", G_TYPE_UINT, wfd_sink->ini.wfd_audio_codecs.audio_codec,
-                                       "audio_latency", G_TYPE_UINT, wfd_sink->ini.wfd_audio_codecs.audio_latency,
-                                       "audio_channels", G_TYPE_UINT, wfd_sink->ini.wfd_audio_codecs.audio_channel,
-                                       "audio_sampling_frequency", G_TYPE_UINT, wfd_sink->ini.wfd_audio_codecs.audio_sampling_frequency,
-                                       NULL);
+                                                                               "audio_codec", G_TYPE_UINT, wfd_sink->ini.wfd_audio_codecs.audio_codec,
+                                                                               "audio_latency", G_TYPE_UINT, wfd_sink->ini.wfd_audio_codecs.audio_latency,
+                                                                               "audio_channels", G_TYPE_UINT, wfd_sink->ini.wfd_audio_codecs.audio_channel,
+                                                                               "audio_sampling_frequency", G_TYPE_UINT, wfd_sink->ini.wfd_audio_codecs.audio_sampling_frequency,
+                                                                               NULL);
 
        if (wfd_audio_codecs) {
                g_object_set(G_OBJECT(wfdsrc), "wfd-audio-codecs", wfd_audio_codecs, NULL);
@@ -1927,22 +2721,22 @@ static int __mm_wfd_sink_prepare_source(mm_wfd_sink_t *wfd_sink, GstElement *wfd
        HH_resolution =  wfd_sink->ini.wfd_video_formats.video_hh_support;
 
        __mm_wfd_sink_prepare_video_resolution(wfd_sink->supportive_resolution,
-                                                                               &CEA_resolution, &VESA_resolution, &HH_resolution);
+                                                                                       &CEA_resolution, &VESA_resolution, &HH_resolution);
        wfd_video_formats = gst_structure_new("wfd_video_formats",
-                                                       "video_codec", G_TYPE_UINT, wfd_sink->ini.wfd_video_formats.video_codec,
-                                                       "video_native_resolution", G_TYPE_UINT, wfd_sink->ini.wfd_video_formats.video_native_resolution,
-                                                       "video_cea_support", G_TYPE_UINT64, CEA_resolution,
-                                                       "video_vesa_support", G_TYPE_UINT64, VESA_resolution,
-                                                       "video_hh_support", G_TYPE_UINT64, HH_resolution,
-                                                       "video_profile", G_TYPE_UINT, wfd_sink->ini.wfd_video_formats.video_profile,
-                                                       "video_level", G_TYPE_UINT, wfd_sink->ini.wfd_video_formats.video_level,
-                                                       "video_latency", G_TYPE_UINT, wfd_sink->ini.wfd_video_formats.video_latency,
-                                                       "video_vertical_resolution", G_TYPE_INT, wfd_sink->ini.wfd_video_formats.video_vertical_resolution,
-                                                       "video_horizontal_resolution", G_TYPE_INT, wfd_sink->ini.wfd_video_formats.video_horizontal_resolution,
-                                                       "video_minimum_slicing", G_TYPE_INT, wfd_sink->ini.wfd_video_formats.video_minimum_slicing,
-                                                       "video_slice_enc_param", G_TYPE_INT, wfd_sink->ini.wfd_video_formats.video_slice_enc_param,
-                                                       "video_framerate_control_support", G_TYPE_INT, wfd_sink->ini.wfd_video_formats.video_framerate_control_support,
-                                                       NULL);
+                                                                               "video_codec", G_TYPE_UINT, wfd_sink->ini.wfd_video_formats.video_codec,
+                                                                               "video_native_resolution", G_TYPE_UINT, wfd_sink->ini.wfd_video_formats.video_native_resolution,
+                                                                               "video_cea_support", G_TYPE_UINT64, CEA_resolution,
+                                                                               "video_vesa_support", G_TYPE_UINT64, VESA_resolution,
+                                                                               "video_hh_support", G_TYPE_UINT64, HH_resolution,
+                                                                               "video_profile", G_TYPE_UINT, wfd_sink->ini.wfd_video_formats.video_profile,
+                                                                               "video_level", G_TYPE_UINT, wfd_sink->ini.wfd_video_formats.video_level,
+                                                                               "video_latency", G_TYPE_UINT, wfd_sink->ini.wfd_video_formats.video_latency,
+                                                                               "video_vertical_resolution", G_TYPE_INT, wfd_sink->ini.wfd_video_formats.video_vertical_resolution,
+                                                                               "video_horizontal_resolution", G_TYPE_INT, wfd_sink->ini.wfd_video_formats.video_horizontal_resolution,
+                                                                               "video_minimum_slicing", G_TYPE_INT, wfd_sink->ini.wfd_video_formats.video_minimum_slicing,
+                                                                               "video_slice_enc_param", G_TYPE_INT, wfd_sink->ini.wfd_video_formats.video_slice_enc_param,
+                                                                               "video_framerate_control_support", G_TYPE_INT, wfd_sink->ini.wfd_video_formats.video_framerate_control_support,
+                                                                               NULL);
 
        if (wfd_video_formats) {
                g_object_set(G_OBJECT(wfdsrc), "wfd-video-formats", wfd_video_formats, NULL);
@@ -1958,9 +2752,9 @@ static int __mm_wfd_sink_prepare_source(mm_wfd_sink_t *wfd_sink, GstElement *wfd
                wfd_sink_debug("set hdcp version %d with %d port", hdcp_version, hdcp_port);
 
                wfd_content_protection = gst_structure_new("wfd_content_protection",
-                                                       "hdcp_version", G_TYPE_INT, hdcp_version,
-                                                       "hdcp_port_no", G_TYPE_INT, hdcp_port,
-                                                       NULL);
+                                                                                                       "hdcp_version", G_TYPE_INT, hdcp_version,
+                                                                                                       "hdcp_port_no", G_TYPE_INT, hdcp_port,
+                                                                                                       NULL);
 
                if (wfd_content_protection) {
                        g_object_set(G_OBJECT(wfdsrc), "wfd-content-protection", wfd_content_protection, NULL);
@@ -1972,11 +2766,11 @@ static int __mm_wfd_sink_prepare_source(mm_wfd_sink_t *wfd_sink, GstElement *wfd
        if (g_object_class_find_property(klass, "wfd2-audio-codecs")) {
                /* set audio parameter for Wi-Fi Display R2 session negotiation */
                wfd2_audio_codecs = gst_structure_new("wfd2-audio-codecs",
-                               "audio_codec", G_TYPE_UINT, wfd_sink->ini.wfd2_audio_codecs.audio_codec,
-                               "audio_lpcm_mode", G_TYPE_UINT, wfd_sink->ini.wfd2_audio_codecs.audio_lpcm_mode,
-                               "audio_aac_mode", G_TYPE_UINT, wfd_sink->ini.wfd2_audio_codecs.audio_aac_mode,
-                               "audio_ac3_mode", G_TYPE_UINT, wfd_sink->ini.wfd2_audio_codecs.audio_ac3_mode,
-                               NULL);
+                                                                                       "audio_codec", G_TYPE_UINT, wfd_sink->ini.wfd2_audio_codecs.audio_codec,
+                                                                                       "audio_lpcm_mode", G_TYPE_UINT, wfd_sink->ini.wfd2_audio_codecs.audio_lpcm_mode,
+                                                                                       "audio_aac_mode", G_TYPE_UINT, wfd_sink->ini.wfd2_audio_codecs.audio_aac_mode,
+                                                                                       "audio_ac3_mode", G_TYPE_UINT, wfd_sink->ini.wfd2_audio_codecs.audio_ac3_mode,
+                                                                                       NULL);
 
                if (wfd2_audio_codecs) {
                        g_object_set(G_OBJECT(wfdsrc), "wfd2-audio-codecs", wfd2_audio_codecs, NULL);
@@ -2050,10 +2844,10 @@ static int __mm_wfd_sink_prepare_source(mm_wfd_sink_t *wfd_sink, GstElement *wfd
        }
 
        wfd_sink->update_stream_info_sig_id = g_signal_connect(wfdsrc, "update-media-info",
-                                               G_CALLBACK(__mm_wfd_sink_update_stream_info), wfd_sink);
+                                                                                                               G_CALLBACK(__mm_wfd_sink_update_stream_info), wfd_sink);
 
        wfd_sink->change_av_format_sig_id = g_signal_connect(wfdsrc, "change-av-format",
-                                               G_CALLBACK(__mm_wfd_sink_change_av_format), wfd_sink);
+                                                                                                               G_CALLBACK(__mm_wfd_sink_change_av_format), wfd_sink);
 
        wfd_sink_debug_fleave();
 
@@ -2068,21 +2862,25 @@ static int __mm_wfd_sink_prepare_demux(mm_wfd_sink_t *wfd_sink, GstElement *demu
        wfd_sink_return_val_if_fail(demux, MM_ERROR_WFD_NOT_INITIALIZED);
 
        g_signal_connect(demux, "pad-added",
-                       G_CALLBACK(__mm_wfd_sink_demux_pad_added),      wfd_sink);
+                                       G_CALLBACK(__mm_wfd_sink_demux_pad_added),      wfd_sink);
 
        wfd_sink_debug_fleave();
 
        return MM_ERROR_NONE;
 }
 
-static void __mm_wfd_sink_queue_overrun(GstElement *element, gpointer u_data)
+static void __mm_wfd_sink_queue_overrun(GstElement *queue, gpointer u_data)
 {
+       guint64 time = 0;
+
        wfd_sink_debug_fenter();
 
-       return_if_fail(element);
+       return_if_fail(queue);
 
-       wfd_sink_warning("%s is overrun",
-                                       GST_STR_NULL(GST_ELEMENT_NAME(element)));
+       g_object_get(G_OBJECT(queue), "current-level-time", &time, NULL);
+
+       wfd_sink_warning("%s is overrun(%" GST_TIME_FORMAT")",
+                                               GST_ELEMENT_NAME(queue), GST_TIME_ARGS(time));
 
        wfd_sink_debug_fleave();
 
@@ -2101,7 +2899,7 @@ static void __mm_wfd_sink_prepare_queue(mm_wfd_sink_t *wfd_sink, GstElement *que
        g_object_set(G_OBJECT(queue), "max-size-buffers", 0, NULL);
        g_object_set(G_OBJECT(queue), "max-size-time", (guint64)3000000000ULL, NULL);
        g_signal_connect(queue, "overrun",
-               G_CALLBACK(__mm_wfd_sink_queue_overrun), wfd_sink);
+                                       G_CALLBACK(__mm_wfd_sink_queue_overrun), wfd_sink);
 
        wfd_sink_debug_fleave();
 
@@ -2170,6 +2968,16 @@ static int __mm_wfd_sink_create_pipeline(mm_wfd_sink_t *wfd_sink)
                }
        }
 
+       /* create valve for audio */
+       MMWFDSINK_CREATE_ELEMENT(mainbin, WFD_SINK_M_A_VALVE, "valve", "audio_valve", FALSE);
+       MMWFDSINK_PAD_PROBE(wfd_sink, NULL, mainbin[WFD_SINK_M_A_VALVE].gst, "src");
+       MMWFDSINK_PAD_PROBE(wfd_sink, NULL, mainbin[WFD_SINK_M_A_VALVE].gst, "sink");
+
+       /* create valve for video */
+       MMWFDSINK_CREATE_ELEMENT(mainbin, WFD_SINK_M_V_VALVE, "valve", "video_valve", FALSE);
+       MMWFDSINK_PAD_PROBE(wfd_sink, NULL, mainbin[WFD_SINK_M_V_VALVE].gst, "src");
+       MMWFDSINK_PAD_PROBE(wfd_sink, NULL, mainbin[WFD_SINK_M_V_VALVE].gst, "sink");
+
        /* adding created elements to pipeline */
        if (!__mm_wfd_sink_gst_element_add_bucket_to_bin(GST_BIN_CAST(mainbin[WFD_SINK_M_PIPE].gst), element_bucket, FALSE)) {
                wfd_sink_error("failed to add elements");
@@ -2263,10 +3071,10 @@ int __mm_wfd_sink_link_audio_decodebin(mm_wfd_sink_t *wfd_sink)
        wfd_sink_debug_fenter();
 
        wfd_sink_return_val_if_fail(wfd_sink &&
-                                               wfd_sink->pipeline &&
-                                               wfd_sink->pipeline->a_decodebin &&
-                                               wfd_sink->pipeline->a_decodebin[WFD_SINK_A_D_BIN].gst,
-                                               MM_ERROR_WFD_NOT_INITIALIZED);
+                                                               wfd_sink->pipeline &&
+                                                               wfd_sink->pipeline->a_decodebin &&
+                                                               wfd_sink->pipeline->a_decodebin[WFD_SINK_A_D_BIN].gst,
+                                                               MM_ERROR_WFD_NOT_INITIALIZED);
 
        if (wfd_sink->audio_decodebin_is_linked) {
                wfd_sink_debug("audio decodebin is already linked... nothing to do");
@@ -2360,7 +3168,7 @@ int __mm_wfd_sink_link_audio_decodebin(mm_wfd_sink_t *wfd_sink)
        sinkpad = gst_element_get_static_pad(GST_ELEMENT(first_element->gst), "sink");
        if (!sinkpad) {
                wfd_sink_error("failed to get sink pad from element(%s)",
-                       GST_STR_NULL(GST_ELEMENT_NAME(first_element->gst)));
+                                               GST_STR_NULL(GST_ELEMENT_NAME(first_element->gst)));
                goto fail_to_link;
        }
 
@@ -2394,7 +3202,7 @@ int __mm_wfd_sink_link_audio_decodebin(mm_wfd_sink_t *wfd_sink)
        srcpad = gst_element_get_static_pad(GST_ELEMENT(last_element->gst), "src");
        if (!srcpad) {
                wfd_sink_error("failed to get src pad from element(%s)",
-                       GST_STR_NULL(GST_ELEMENT_NAME(last_element->gst)));
+                                               GST_STR_NULL(GST_ELEMENT_NAME(last_element->gst)));
                goto fail_to_link;
        }
 
@@ -2495,14 +3303,14 @@ static int  __mm_wfd_sink_destroy_audio_decodebin(mm_wfd_sink_t *wfd_sink)
                                parent = gst_element_get_parent(a_decodebin[i].gst);
                                if (!parent) {
                                        wfd_sink_debug("unref %s(current ref %d)",
-                                                       GST_STR_NULL(GST_ELEMENT_NAME(a_decodebin[i].gst)),
-                                                       ((GObject *) a_decodebin[i].gst)->ref_count);
+                                                                       GST_STR_NULL(GST_ELEMENT_NAME(a_decodebin[i].gst)),
+                                                                       ((GObject *) a_decodebin[i].gst)->ref_count);
                                        gst_object_unref(GST_OBJECT(a_decodebin[i].gst));
                                        a_decodebin[i].gst = NULL;
                                } else {
                                        wfd_sink_debug("%s has parent.(current ref %d)",
-                                                       GST_STR_NULL(GST_ELEMENT_NAME(a_decodebin[i].gst)),
-                                                       ((GObject *) a_decodebin[i].gst)->ref_count);
+                                                                       GST_STR_NULL(GST_ELEMENT_NAME(a_decodebin[i].gst)),
+                                                                       ((GObject *) a_decodebin[i].gst)->ref_count);
                                        gst_object_unref(GST_OBJECT(parent));
                                        parent = NULL;
                                }
@@ -2517,7 +3325,7 @@ static int  __mm_wfd_sink_destroy_audio_decodebin(mm_wfd_sink_t *wfd_sink)
 
        } else {
                wfd_sink_debug("audio decodebin has parent(%s), unref it ",
-                                       GST_STR_NULL(GST_OBJECT_NAME(GST_OBJECT(parent))));
+                                               GST_STR_NULL(GST_OBJECT_NAME(GST_OBJECT(parent))));
 
                gst_object_unref(GST_OBJECT(parent));
                parent = NULL;
@@ -2543,8 +3351,8 @@ int __mm_wfd_sink_create_audio_decodebin(mm_wfd_sink_t *wfd_sink)
        wfd_sink_debug_fenter();
 
        wfd_sink_return_val_if_fail(wfd_sink &&
-                                               wfd_sink->pipeline,
-                                               MM_ERROR_WFD_NOT_INITIALIZED);
+                                                               wfd_sink->pipeline,
+                                                               MM_ERROR_WFD_NOT_INITIALIZED);
 
        if (wfd_sink->pipeline->a_decodebin != NULL) {
                wfd_sink_error("The audio decode bin is already created.");
@@ -2593,12 +3401,14 @@ int __mm_wfd_sink_create_audio_decodebin(mm_wfd_sink_t *wfd_sink)
        /* create queue */
        MMWFDSINK_CREATE_ELEMENT(a_decodebin, WFD_SINK_A_D_QUEUE, "queue", "audio_queue", FALSE);
        MMWFDSINK_PAD_PROBE(wfd_sink, NULL, a_decodebin[WFD_SINK_A_D_QUEUE].gst,  "sink");
+       MMWFDSINK_PAD_PROBE(wfd_sink, NULL, a_decodebin[WFD_SINK_A_D_QUEUE].gst,  "src");
        if (a_decodebin[WFD_SINK_A_D_QUEUE].gst)
                __mm_wfd_sink_prepare_queue(wfd_sink, a_decodebin[WFD_SINK_A_D_QUEUE].gst);
 
        /* create hdcp */
        MMWFDSINK_CREATE_ELEMENT(a_decodebin, WFD_SINK_A_D_HDCP, wfd_sink->ini.name_of_audio_hdcp, "audio_hdcp", FALSE);
        MMWFDSINK_PAD_PROBE(wfd_sink, NULL, a_decodebin[WFD_SINK_A_D_HDCP].gst,  "sink");
+       MMWFDSINK_PAD_PROBE(wfd_sink, NULL, a_decodebin[WFD_SINK_A_D_HDCP].gst,  "src");
 
        /* create codec */
        audio_codec = wfd_sink->ini.wfd_audio_codecs.audio_codec;
@@ -2727,14 +3537,14 @@ static int  __mm_wfd_sink_destroy_audio_sinkbin(mm_wfd_sink_t *wfd_sink)
                                parent = gst_element_get_parent(a_sinkbin[i].gst);
                                if (!parent) {
                                        wfd_sink_debug("unref %s(current ref %d)",
-                                                       GST_STR_NULL(GST_ELEMENT_NAME(a_sinkbin[i].gst)),
-                                                       ((GObject *) a_sinkbin[i].gst)->ref_count);
+                                                                       GST_STR_NULL(GST_ELEMENT_NAME(a_sinkbin[i].gst)),
+                                                                       ((GObject *) a_sinkbin[i].gst)->ref_count);
                                        gst_object_unref(GST_OBJECT(a_sinkbin[i].gst));
                                        a_sinkbin[i].gst = NULL;
                                } else {
                                        wfd_sink_debug("%s has parent.(current ref %d)",
-                                                       GST_STR_NULL(GST_ELEMENT_NAME(a_sinkbin[i].gst)),
-                                                       ((GObject *) a_sinkbin[i].gst)->ref_count);
+                                                                       GST_STR_NULL(GST_ELEMENT_NAME(a_sinkbin[i].gst)),
+                                                                       ((GObject *) a_sinkbin[i].gst)->ref_count);
                                        gst_object_unref(GST_OBJECT(parent));
                                        parent = NULL;
                                }
@@ -2748,7 +3558,7 @@ static int  __mm_wfd_sink_destroy_audio_sinkbin(mm_wfd_sink_t *wfd_sink)
                }
        } else {
                wfd_sink_debug("audio sinkbin has parent(%s), unref it ",
-                                       GST_STR_NULL(GST_OBJECT_NAME(GST_OBJECT(parent))));
+                                               GST_STR_NULL(GST_OBJECT_NAME(GST_OBJECT(parent))));
 
                gst_object_unref(GST_OBJECT(parent));
                parent = NULL;
@@ -2774,8 +3584,8 @@ int __mm_wfd_sink_create_audio_sinkbin(mm_wfd_sink_t *wfd_sink)
        wfd_sink_debug_fenter();
 
        wfd_sink_return_val_if_fail(wfd_sink &&
-                                               wfd_sink->pipeline,
-                                               MM_ERROR_WFD_NOT_INITIALIZED);
+                                                               wfd_sink->pipeline,
+                                                               MM_ERROR_WFD_NOT_INITIALIZED);
 
        if (wfd_sink->pipeline->a_sinkbin != NULL) {
                wfd_sink_error("The audio sink bin is already created.");
@@ -2801,13 +3611,13 @@ int __mm_wfd_sink_create_audio_sinkbin(mm_wfd_sink_t *wfd_sink)
 
        /* create resampler */
        MMWFDSINK_CREATE_ELEMENT(a_sinkbin, WFD_SINK_A_S_RESAMPLER,
-                       wfd_sink->ini.name_of_audio_resampler, "audio_resampler", TRUE);
+                                                       wfd_sink->ini.name_of_audio_resampler, "audio_resampler", TRUE);
        MMWFDSINK_PAD_PROBE(wfd_sink, NULL, a_sinkbin[WFD_SINK_A_S_RESAMPLER].gst,  "sink");
        MMWFDSINK_PAD_PROBE(wfd_sink, NULL, a_sinkbin[WFD_SINK_A_S_RESAMPLER].gst,  "src");
 
        /* create volume */
        MMWFDSINK_CREATE_ELEMENT(a_sinkbin, WFD_SINK_A_S_VOLUME,
-                       wfd_sink->ini.name_of_audio_volume, "audio_volume", TRUE);
+                                                       wfd_sink->ini.name_of_audio_volume, "audio_volume", TRUE);
        MMWFDSINK_PAD_PROBE(wfd_sink, NULL, a_sinkbin[WFD_SINK_A_S_VOLUME].gst,  "sink");
        MMWFDSINK_PAD_PROBE(wfd_sink, NULL, a_sinkbin[WFD_SINK_A_S_VOLUME].gst,  "src");
 
@@ -2818,7 +3628,7 @@ int __mm_wfd_sink_create_audio_sinkbin(mm_wfd_sink_t *wfd_sink)
 
        /* create sink */
        MMWFDSINK_CREATE_ELEMENT(a_sinkbin, WFD_SINK_A_S_SINK,
-                       wfd_sink->ini.name_of_audio_sink, "audio_sink", TRUE);
+                                                       wfd_sink->ini.name_of_audio_sink, "audio_sink", TRUE);
        MMWFDSINK_PAD_PROBE(wfd_sink, NULL, a_sinkbin[WFD_SINK_A_S_SINK].gst,  "sink");
        if (a_sinkbin[WFD_SINK_A_S_SINK].gst) {
                if (MM_ERROR_NONE != __mm_wfd_sink_prepare_audiosink(wfd_sink, a_sinkbin[WFD_SINK_A_S_SINK].gst)) {
@@ -2856,7 +3666,7 @@ int __mm_wfd_sink_create_audio_sinkbin(mm_wfd_sink_t *wfd_sink)
        pad = gst_element_get_static_pad(GST_ELEMENT(first_element->gst), "sink");
        if (!pad) {
                wfd_sink_error("failed to get sink pad from element(%s)",
-                       GST_STR_NULL(GST_ELEMENT_NAME(first_element->gst)));
+                                               GST_STR_NULL(GST_ELEMENT_NAME(first_element->gst)));
                goto CREATE_ERROR;
        }
 
@@ -2939,10 +3749,10 @@ int __mm_wfd_sink_link_video_decodebin(mm_wfd_sink_t *wfd_sink)
        wfd_sink_debug_fenter();
 
        wfd_sink_return_val_if_fail(wfd_sink &&
-                                               wfd_sink->pipeline &&
-                                               wfd_sink->pipeline->v_decodebin &&
-                                               wfd_sink->pipeline->v_decodebin[WFD_SINK_V_D_BIN].gst,
-                                               MM_ERROR_WFD_NOT_INITIALIZED);
+                                                               wfd_sink->pipeline &&
+                                                               wfd_sink->pipeline->v_decodebin &&
+                                                               wfd_sink->pipeline->v_decodebin[WFD_SINK_V_D_BIN].gst,
+                                                               MM_ERROR_WFD_NOT_INITIALIZED);
 
        if (wfd_sink->video_decodebin_is_linked) {
                wfd_sink_debug("video decodebin is already linked... nothing to do");
@@ -3019,7 +3829,7 @@ int __mm_wfd_sink_link_video_decodebin(mm_wfd_sink_t *wfd_sink)
        sinkpad = gst_element_get_static_pad(GST_ELEMENT(first_element->gst), "sink");
        if (!sinkpad) {
                wfd_sink_error("failed to get sink pad from element(%s)",
-                       GST_STR_NULL(GST_ELEMENT_NAME(first_element->gst)));
+                                               GST_STR_NULL(GST_ELEMENT_NAME(first_element->gst)));
                goto fail_to_link;
        }
 
@@ -3053,7 +3863,7 @@ int __mm_wfd_sink_link_video_decodebin(mm_wfd_sink_t *wfd_sink)
        srcpad = gst_element_get_static_pad(GST_ELEMENT(last_element->gst), "src");
        if (!srcpad) {
                wfd_sink_error("failed to get src pad from element(%s)",
-                       GST_STR_NULL(GST_ELEMENT_NAME(last_element->gst)));
+                                               GST_STR_NULL(GST_ELEMENT_NAME(last_element->gst)));
                goto fail_to_link;
        }
 
@@ -3148,11 +3958,12 @@ static int __mm_wfd_sink_prepare_videosink(mm_wfd_sink_t *wfd_sink, GstElement *
                        break;
 
                case MM_DISPLAY_SURFACE_OVERLAY: {
+                               static unsigned int wl_surface_id = 0;
+                               static void *display_overlay = NULL;
                                int wl_window_x = 0;
                                int wl_window_y = 0;
                                int wl_window_width = 0;
                                int wl_window_height = 0;
-                               unsigned int wl_surface_id = 0;
                                struct wl_surface *wl_surface = NULL;
                                struct wl_display *wl_display = NULL;
                                Ecore_Wl_Window *wl_window = NULL;
@@ -3174,7 +3985,7 @@ static int __mm_wfd_sink_prepare_videosink(mm_wfd_sink_t *wfd_sink, GstElement *
                                        evas_object_geometry_get(obj, &wl_window_x, &wl_window_y, &wl_window_width, &wl_window_height);
 
                                        wfd_sink_debug("x[%d] y[%d] width[%d] height[%d]", wl_window_x, wl_window_y,
-                                               wl_window_width, wl_window_height);
+                                                                       wl_window_width, wl_window_height);
 
                                        wl_window = elm_win_wl_window_get(obj);
                                        wl_surface = (struct wl_surface *) ecore_wl_window_surface_get(wl_window);
@@ -3182,28 +3993,33 @@ static int __mm_wfd_sink_prepare_videosink(mm_wfd_sink_t *wfd_sink, GstElement *
                                        /* get wl_display */
                                        wl_display = (struct wl_display *) ecore_wl_display_get();
 
-                                       ret = mm_wfd_sink_wlclient_create(&wlclient);
-                                       if (ret != MM_ERROR_NONE) {
-                                               wfd_sink_error("Wayland client create failure");
-                                               return ret;
-                                       }
-
-                                       if (wl_surface && wl_display) {
+                                       wfd_sink_debug("previous display object : %p current object : %p", display_overlay, object);
+                                       if (wl_surface && wl_display && (wl_surface_id == 0 || display_overlay != object)) {
                                                wfd_sink_debug("surface = %p, wl_display = %p", wl_surface, wl_display);
+                                               display_overlay = object;
+
+                                               ret = mm_wfd_sink_wlclient_create(&wlclient);
+                                               if (ret != MM_ERROR_NONE) {
+                                                       wfd_sink_error("Wayland client create failure");
+                                                       return ret;
+                                               }
+                                               wfd_sink_debug("Try to get surface id");
+
                                                wl_surface_id = mm_wfd_sink_wlclient_get_wl_window_wl_surface_id(wlclient, wl_surface, wl_display);
+
                                                wfd_sink_debug("wl_surface_id = %d", wl_surface_id);
-                                       }
-                                       if (wlclient) {
-                                               g_free(wlclient);
-                                               wlclient = NULL;
-                                       }
 
+                                               if (wlclient) {
+                                                       g_free(wlclient);
+                                                       wlclient = NULL;
+                                               }
+                                       }
                                        wfd_sink_debug("set video param : surface_id %d", wl_surface_id);
                                        gst_video_overlay_set_wl_window_wl_surface_id(GST_VIDEO_OVERLAY(video_sink),
-                                               wl_surface_id);
+                                                                                                                               wl_surface_id);
                                        /* After setting window handle, set render rectangle */
                                        gst_video_overlay_set_render_rectangle(GST_VIDEO_OVERLAY(video_sink),
-                                               wl_window_x, wl_window_y, wl_window_width, wl_window_height);
+                                                                                                                       wl_window_x, wl_window_y, wl_window_width, wl_window_height);
                                } else {
                                        wfd_sink_debug("display object is NULL!");
                                        return MM_ERROR_WFD_INTERNAL;
@@ -3274,14 +4090,14 @@ static int __mm_wfd_sink_destroy_video_decodebin(mm_wfd_sink_t *wfd_sink)
                                parent = gst_element_get_parent(v_decodebin[i].gst);
                                if (!parent) {
                                        wfd_sink_debug("unref %s(current ref %d)",
-                                                               GST_STR_NULL(GST_ELEMENT_NAME(v_decodebin[i].gst)),
-                                                               ((GObject *) v_decodebin[i].gst)->ref_count);
+                                                                       GST_STR_NULL(GST_ELEMENT_NAME(v_decodebin[i].gst)),
+                                                                       ((GObject *) v_decodebin[i].gst)->ref_count);
                                        gst_object_unref(GST_OBJECT(v_decodebin[i].gst));
                                        v_decodebin[i].gst = NULL;
                                } else {
                                        wfd_sink_debug("%s has parent.(current ref %d)",
-                                                               GST_STR_NULL(GST_ELEMENT_NAME(v_decodebin[i].gst)),
-                                                               ((GObject *) v_decodebin[i].gst)->ref_count);
+                                                                       GST_STR_NULL(GST_ELEMENT_NAME(v_decodebin[i].gst)),
+                                                                       ((GObject *) v_decodebin[i].gst)->ref_count);
                                        gst_object_unref(GST_OBJECT(parent));
                                        parent = NULL;
                                }
@@ -3290,15 +4106,15 @@ static int __mm_wfd_sink_destroy_video_decodebin(mm_wfd_sink_t *wfd_sink)
                /* release video decodebin with it's childs */
                if (v_decodebin[WFD_SINK_V_D_BIN].gst) {
                        wfd_sink_debug("unref %s(current ref %d)",
-                                               GST_STR_NULL(GST_ELEMENT_NAME(v_decodebin[WFD_SINK_V_D_BIN].gst)),
-                                               ((GObject *)v_decodebin[WFD_SINK_V_D_BIN].gst)->ref_count);
+                                                       GST_STR_NULL(GST_ELEMENT_NAME(v_decodebin[WFD_SINK_V_D_BIN].gst)),
+                                                       ((GObject *)v_decodebin[WFD_SINK_V_D_BIN].gst)->ref_count);
 
                        gst_object_unref(GST_OBJECT(v_decodebin[WFD_SINK_V_D_BIN].gst));
                        v_decodebin[WFD_SINK_V_D_BIN].gst = NULL;
                }
        } else {
                wfd_sink_debug("video decodebin has parent(%s), unref it",
-                                       GST_STR_NULL(GST_OBJECT_NAME(GST_OBJECT(parent))));
+                                               GST_STR_NULL(GST_OBJECT_NAME(GST_OBJECT(parent))));
 
                gst_object_unref(GST_OBJECT(parent));
                parent = NULL;
@@ -3324,8 +4140,8 @@ int __mm_wfd_sink_create_video_decodebin(mm_wfd_sink_t *wfd_sink)
        wfd_sink_debug_fenter();
 
        wfd_sink_return_val_if_fail(wfd_sink &&
-                                               wfd_sink->pipeline,
-                                               MM_ERROR_WFD_NOT_INITIALIZED);
+                                                               wfd_sink->pipeline,
+                                                               MM_ERROR_WFD_NOT_INITIALIZED);
 
        if (wfd_sink->pipeline->v_decodebin) {
                wfd_sink_debug("video decodebin is already created... nothing to do");
@@ -3370,6 +4186,7 @@ int __mm_wfd_sink_create_video_decodebin(mm_wfd_sink_t *wfd_sink)
        /* create queue */
        MMWFDSINK_CREATE_ELEMENT(v_decodebin, WFD_SINK_V_D_QUEUE, "queue", "video_queue", FALSE);
        MMWFDSINK_PAD_PROBE(wfd_sink, NULL, v_decodebin[WFD_SINK_V_D_QUEUE].gst,  "sink");
+       MMWFDSINK_PAD_PROBE(wfd_sink, NULL, v_decodebin[WFD_SINK_V_D_QUEUE].gst,  "src");
        if (v_decodebin[WFD_SINK_V_D_QUEUE].gst)
                __mm_wfd_sink_prepare_queue(wfd_sink, v_decodebin[WFD_SINK_V_D_QUEUE].gst);
 
@@ -3504,14 +4321,14 @@ static int __mm_wfd_sink_destroy_video_sinkbin(mm_wfd_sink_t *wfd_sink)
                                parent = gst_element_get_parent(v_sinkbin[i].gst);
                                if (!parent) {
                                        wfd_sink_debug("unref %s(current ref %d)",
-                                                               GST_STR_NULL(GST_ELEMENT_NAME(v_sinkbin[i].gst)),
-                                                               ((GObject *) v_sinkbin[i].gst)->ref_count);
+                                                                       GST_STR_NULL(GST_ELEMENT_NAME(v_sinkbin[i].gst)),
+                                                                       ((GObject *) v_sinkbin[i].gst)->ref_count);
                                        gst_object_unref(GST_OBJECT(v_sinkbin[i].gst));
                                        v_sinkbin[i].gst = NULL;
                                } else {
                                        wfd_sink_debug("%s has parent.(current ref %d)",
-                                                               GST_STR_NULL(GST_ELEMENT_NAME(v_sinkbin[i].gst)),
-                                                               ((GObject *) v_sinkbin[i].gst)->ref_count);
+                                                                       GST_STR_NULL(GST_ELEMENT_NAME(v_sinkbin[i].gst)),
+                                                                       ((GObject *) v_sinkbin[i].gst)->ref_count);
                                        gst_object_unref(GST_OBJECT(parent));
                                        parent = NULL;
                                }
@@ -3524,7 +4341,7 @@ static int __mm_wfd_sink_destroy_video_sinkbin(mm_wfd_sink_t *wfd_sink)
                }
        } else {
                wfd_sink_debug("video sinkbin has parent(%s), unref it ",
-                                       GST_STR_NULL(GST_OBJECT_NAME(GST_OBJECT(parent))));
+                                               GST_STR_NULL(GST_OBJECT_NAME(GST_OBJECT(parent))));
 
                gst_object_unref(GST_OBJECT(parent));
                parent = NULL;
@@ -3550,8 +4367,8 @@ int __mm_wfd_sink_create_video_sinkbin(mm_wfd_sink_t *wfd_sink)
        wfd_sink_debug_fenter();
 
        wfd_sink_return_val_if_fail(wfd_sink &&
-                                               wfd_sink->pipeline,
-                                               MM_ERROR_WFD_NOT_INITIALIZED);
+                                                               wfd_sink->pipeline,
+                                                               MM_ERROR_WFD_NOT_INITIALIZED);
 
        if (wfd_sink->pipeline->v_sinkbin != NULL) {
                wfd_sink_error("The video sink bin is already created.");
@@ -3634,7 +4451,7 @@ int __mm_wfd_sink_create_video_sinkbin(mm_wfd_sink_t *wfd_sink)
        pad = gst_element_get_static_pad(GST_ELEMENT(first_element->gst), "sink");
        if (!pad) {
                wfd_sink_error("failed to get pad from first element(%s) of the video sinkbin",
-                       GST_STR_NULL(GST_ELEMENT_NAME(first_element->gst)));
+                                               GST_STR_NULL(GST_ELEMENT_NAME(first_element->gst)));
                goto CREATE_ERROR;
        }
 
@@ -3710,6 +4527,7 @@ CREATE_ERROR:
 static int __mm_wfd_sink_destroy_pipeline(mm_wfd_sink_t *wfd_sink)
 {
        GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
+       GstBus *bus = NULL;
 
        wfd_sink_debug_fenter();
 
@@ -3720,6 +4538,9 @@ static int __mm_wfd_sink_destroy_pipeline(mm_wfd_sink_t *wfd_sink)
                MMWFDSinkGstElement *mainbin = wfd_sink->pipeline->mainbin;
 
                if (mainbin) {
+
+                       PRINT_WFD_REF_COUNT(wfd_sink);
+
                        ret = gst_element_set_state(mainbin[WFD_SINK_M_PIPE].gst, GST_STATE_NULL);
                        if (ret != GST_STATE_CHANGE_SUCCESS) {
                                wfd_sink_error("failed to change state of pipeline to NULL");
@@ -3728,6 +4549,20 @@ static int __mm_wfd_sink_destroy_pipeline(mm_wfd_sink_t *wfd_sink)
                                wfd_sink_debug("Successed to change state of pipeline to NULL");
                        }
 
+                       bus = gst_pipeline_get_bus(GST_PIPELINE(mainbin[WFD_SINK_M_PIPE].gst));
+                       if (bus) {
+                               GstMessage *gst_msg = NULL;
+                               while ((gst_msg = gst_bus_pop(bus)) != NULL) {
+                                       _mm_wfd_sink_msg_callback(bus, gst_msg, (gpointer)wfd_sink);
+                                       gst_message_unref(gst_msg);
+                                       gst_msg = NULL;
+                               }
+                               gst_object_unref(bus);
+                               bus = NULL;
+                       }
+
+                       PRINT_WFD_REF_COUNT(wfd_sink);
+
                        if (MM_ERROR_NONE != __mm_wfd_sink_destroy_video_decodebin(wfd_sink)) {
                                wfd_sink_error("failed to destroy video decodebin");
                                return MM_ERROR_WFD_INTERNAL;
@@ -3787,9 +4622,9 @@ __mm_wfd_sink_dump_pipeline_state(mm_wfd_sink_t *wfd_sink)
        wfd_sink_debug_fenter();
 
        wfd_sink_return_if_fail(wfd_sink &&
-                                               wfd_sink->pipeline &&
-                                               wfd_sink->pipeline->mainbin &&
-                                               wfd_sink->pipeline->mainbin[WFD_SINK_M_PIPE].gst);
+                                                       wfd_sink->pipeline &&
+                                                       wfd_sink->pipeline->mainbin &&
+                                                       wfd_sink->pipeline->mainbin[WFD_SINK_M_PIPE].gst);
 
        iter = gst_bin_iterate_recurse(GST_BIN(wfd_sink->pipeline->mainbin[WFD_SINK_M_PIPE].gst));
 
@@ -3834,11 +4669,11 @@ __mm_wfd_sink_dump_pipeline_state(mm_wfd_sink_t *wfd_sink)
        factory = gst_element_get_factory(item) ;
        if (factory) {
                wfd_sink_error("%s:%s : From:%s To:%s refcount : %d",
-                                       GST_OBJECT_NAME(factory),
-                                       GST_ELEMENT_NAME(item),
-                                       gst_element_state_get_name(state),
-                                       gst_element_state_get_name(pending),
-                                       GST_OBJECT_REFCOUNT_VALUE(item));
+                                               GST_OBJECT_NAME(factory),
+                                               GST_ELEMENT_NAME(item),
+                                               gst_element_state_get_name(state),
+                                               gst_element_state_get_name(pending),
+                                               GST_OBJECT_REFCOUNT_VALUE(item));
        }
 
        if (iter)
@@ -3893,3 +4728,96 @@ int _mm_wfd_sink_set_resolution(mm_wfd_sink_t *wfd_sink, MMWFDSinkResolution res
 
        return MM_ERROR_NONE;
 }
+
+void __mm_wfd_sink_print_ref_count(mm_wfd_sink_t *wfd_sink)
+{
+       int i = 0;
+       MMWFDSinkGstElement *mainbin = NULL;
+       MMWFDSinkGstElement *v_decodebin = NULL;
+       MMWFDSinkGstElement *a_decodebin = NULL;
+       MMWFDSinkGstElement *v_sinkbin = NULL;
+       MMWFDSinkGstElement *a_sinkbin = NULL;
+
+       wfd_sink_debug_fenter();
+
+       wfd_sink_return_if_fail(wfd_sink);
+       wfd_sink_return_if_fail(wfd_sink->pipeline);
+
+       wfd_sink_debug("************* wfd pipeline ref count start *************");
+       wfd_sink_debug("try to check mainbin");
+
+       if (wfd_sink->pipeline->mainbin &&
+           wfd_sink->pipeline->mainbin[WFD_SINK_M_PIPE].gst) {
+               mainbin = wfd_sink->pipeline->mainbin;
+
+               for (i = 0; i < WFD_SINK_M_NUM; i++) {
+                       if (mainbin[i].gst) {
+                               wfd_sink_debug("%s(current ref %d)",
+                                                               GST_ELEMENT_NAME(mainbin[i].gst),
+                                                               GST_OBJECT_REFCOUNT(mainbin[i].gst));
+                       }
+               }
+       }
+
+       wfd_sink_debug("try to check a_decodebin");
+
+       if (wfd_sink->pipeline->a_decodebin &&
+           wfd_sink->pipeline->a_decodebin[WFD_SINK_A_D_BIN].gst) {
+               a_decodebin = wfd_sink->pipeline->a_decodebin;
+
+               for (i = 0; i < WFD_SINK_A_D_NUM; i++) {
+                       if (a_decodebin[i].gst) {
+                               wfd_sink_debug("%s(current ref %d)",
+                                                               GST_ELEMENT_NAME(a_decodebin[i].gst),
+                                                               GST_OBJECT_REFCOUNT(a_decodebin[i].gst));
+                       }
+               }
+       }
+
+       wfd_sink_debug("try to check a_sinkbin");
+
+       if (wfd_sink->pipeline->a_sinkbin &&
+           wfd_sink->pipeline->a_sinkbin[WFD_SINK_A_S_BIN].gst) {
+               a_sinkbin = wfd_sink->pipeline->a_sinkbin;
+
+               for (i = 0; i < WFD_SINK_A_S_NUM; i++) {
+                       if (a_sinkbin[i].gst) {
+                               wfd_sink_debug("%s(current ref %d)",
+                                                               GST_ELEMENT_NAME(a_sinkbin[i].gst),
+                                                               GST_OBJECT_REFCOUNT(a_sinkbin[i].gst));
+                       }
+               }
+       }
+
+       wfd_sink_debug("try to check v_decodebin");
+
+       if (wfd_sink->pipeline->v_decodebin &&
+           wfd_sink->pipeline->v_decodebin[WFD_SINK_V_D_BIN].gst) {
+               v_decodebin = wfd_sink->pipeline->v_decodebin;
+
+               for (i = 0; i < WFD_SINK_V_D_NUM; i++) {
+                       if (v_decodebin[i].gst) {
+                               wfd_sink_debug("%s(current ref %d)",
+                                                               GST_ELEMENT_NAME(v_decodebin[i].gst),
+                                                               GST_OBJECT_REFCOUNT(v_decodebin[i].gst));
+                       }
+               }
+       }
+
+       wfd_sink_debug("try to check v_sinkbin");
+
+       if (wfd_sink->pipeline->v_sinkbin &&
+           wfd_sink->pipeline->v_sinkbin[WFD_SINK_V_S_BIN].gst) {
+               v_sinkbin = wfd_sink->pipeline->v_sinkbin;
+
+               for (i = 0; i < WFD_SINK_V_S_NUM; i++) {
+                       if (v_sinkbin[i].gst) {
+                               wfd_sink_debug("%s(current ref %d)",
+                                                               GST_ELEMENT_NAME(v_sinkbin[i].gst),
+                                                               GST_OBJECT_REFCOUNT(v_sinkbin[i].gst));
+                       }
+               }
+       }
+       wfd_sink_debug("************* wfd pipeline ref count end *************");
+       wfd_sink_debug_fleave();
+}