Add sink_msg_callback function.
[platform/core/multimedia/libmm-wfd.git] / src / mm_wfd_sink_priv.c
index f87f5b7..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_create_audio_decodebin(mm_wfd_sink_t *wfd_sink);
-static int __mm_wfd_sink_create_video_decodebin(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_create_video_sinkbin(mm_wfd_sink_t *wfd_sink);
-static int __mm_wfd_sink_create_audio_sinkbin(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_check_state(mm_wfd_sink_t *wfd_sink, MMWFDSinkCommandType cmd);
 static int __mm_wfd_sink_set_state(mm_wfd_sink_t *wfd_sink, MMWFDSinkStateType state);
 
 /* util */
@@ -243,15 +247,16 @@ 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);
+       wfd_sink_return_val_if_fail(uri && strlen(uri) > strlen("rtsp://"),
+                                                               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);
@@ -306,16 +311,16 @@ 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);
 
-       g_signal_emit_by_name(wfd_sink->pipeline->mainbin[WFD_SINK_M_SRC].gst, "pause", NULL);
+       g_signal_emit_by_name(wfd_sink->pipeline->mainbin[WFD_SINK_M_SRC].gst, "request-pause", NULL);
 
        wfd_sink_debug_fleave();
 
@@ -329,16 +334,16 @@ 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);
 
-       g_signal_emit_by_name(wfd_sink->pipeline->mainbin[WFD_SINK_M_SRC].gst, "resume", NULL);
+       g_signal_emit_by_name(wfd_sink->pipeline->mainbin[WFD_SINK_M_SRC].gst, "request-resume", NULL);
 
        wfd_sink_debug_fleave();
 
@@ -352,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);
@@ -364,7 +369,7 @@ int _mm_wfd_sink_disconnect(mm_wfd_sink_t *wfd_sink)
        WFD_SINK_MANAGER_APPEND_CMD(wfd_sink, WFD_SINK_MANAGER_CMD_EXIT);
        WFD_SINK_MANAGER_SIGNAL_CMD(wfd_sink);
 
-       g_signal_emit_by_name(wfd_sink->pipeline->mainbin[WFD_SINK_M_SRC].gst, "close", NULL);
+       g_signal_emit_by_name(wfd_sink->pipeline->mainbin[WFD_SINK_M_SRC].gst, "request-close", NULL);
 
        wfd_sink_debug_fleave();
 
@@ -419,12 +424,12 @@ int _mm_wfd_sink_destroy(mm_wfd_sink_t *wfd_sink)
        /* release attributes */
        _mmwfd_deconstruct_attribute(wfd_sink->attrs);
 
+       /* release manager thread  */
        if (MM_ERROR_NONE != _mm_wfd_sink_release_manager(wfd_sink)) {
                wfd_sink_error("failed to release manager");
                return MM_ERROR_WFD_INTERNAL;
        }
 
-
        /* set state */
        __mm_wfd_sink_set_state(wfd_sink,  MM_WFD_SINK_STATE_NONE);
 
@@ -496,13 +501,13 @@ static int __mm_wfd_sink_init_gstreamer(mm_wfd_sink_t *wfd_sink)
        wfd_sink_debug("initializing gstreamer with following parameter");
        wfd_sink_debug("argc : %d", *argc);
 
-       for (i = 0; i < *argc; i++) {
+       for (i = 0; i < *argc; i++)
                wfd_sink_debug("argv[%d] : %s", i, argv[i]);
-       }
 
        /* initializing gstreamer */
        if (!gst_init_check(argc, &argv, &err)) {
-               wfd_sink_error("failed to initialize gstreamer: %s", err ? err->message : "unknown error occurred");
+               wfd_sink_error("failed to initialize gstreamer: %s",
+                                               err ? err->message : "unknown error occurred");
                if (err)
                        g_error_free(err);
 
@@ -510,9 +515,9 @@ static int __mm_wfd_sink_init_gstreamer(mm_wfd_sink_t *wfd_sink)
        }
 
        /* release */
-       for (i = 0; i < *argc; i++) {
+       for (i = 0; i < *argc; i++)
                MMWFDSINK_FREEIF(argv[i]);
-       }
+
        MMWFDSINK_FREEIF(argv);
        MMWFDSINK_FREEIF(argc);
 
@@ -527,33 +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));
 
        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)
 {
@@ -564,244 +793,248 @@ _mm_wfd_sink_msg_callback(GstBus *bus, GstMessage *msg, gpointer data)
        wfd_sink_return_val_if_fail(wfd_sink, FALSE);
        wfd_sink_return_val_if_fail(msg && GST_IS_MESSAGE(msg), FALSE);
 
-       wfd_sink_debug("got %s from %s",
+       wfd_sink_debug("got %s(%d) from %s",
                                        GST_STR_NULL(GST_MESSAGE_TYPE_NAME(msg)),
+                                       GST_MESSAGE_TYPE(msg),
                                        GST_STR_NULL(GST_OBJECT_NAME(GST_MESSAGE_SRC(msg))));
 
        switch (GST_MESSAGE_TYPE(msg)) {
-               case GST_MESSAGE_ERROR: {
-                               GError *error = NULL;
-                               gchar *debug = NULL;
-
-                               /* get error code */
-                               gst_message_parse_error(msg, &error, &debug);
+       case GST_MESSAGE_ERROR: {
+                       GError *error = NULL;
+                       gchar *debug = NULL;
 
-                               wfd_sink_error("error : %s", error->message);
-                               wfd_sink_error("debug : %s", debug);
+                       /* get error code */
+                       gst_message_parse_error(msg, &error, &debug);
 
-                               MMWFDSINK_FREEIF(debug);
-                               g_error_free(error);
-                       }
-                       break;
+                       wfd_sink_error("error : %s", error->message);
+                       wfd_sink_error("debug : %s", debug);
 
-               case GST_MESSAGE_WARNING: {
-                               char *debug = NULL;
-                               GError *error = NULL;
-
-                               gst_message_parse_warning(msg, &error, &debug);
+                       MMWFDSINK_FREEIF(debug);
+                       g_error_free(error);
+               }
+               break;
 
-                               wfd_sink_warning("warning : %s", error->message);
-                               wfd_sink_warning("debug : %s", debug);
+       case GST_MESSAGE_WARNING: {
+                       char *debug = NULL;
+                       GError *error = NULL;
 
-                               MMWFDSINK_FREEIF(debug);
-                               g_error_free(error);
-                       }
-                       break;
+                       gst_message_parse_warning(msg, &error, &debug);
 
-               case GST_MESSAGE_STATE_CHANGED: {
-                               const GValue *voldstate, *vnewstate, *vpending;
-                               GstState oldstate, newstate, pending;
-                               const GstStructure *structure;
-
-                               /* we only handle messages from pipeline */
-                               if (msg->src != (GstObject *)wfd_sink->pipeline->mainbin[WFD_SINK_M_PIPE].gst)
-                                       break;
-
-                               /* get state info from msg */
-                               structure = gst_message_get_structure(msg);
-                               if (structure == NULL)
-                                       break;
-
-                               voldstate = gst_structure_get_value(structure, "old-state");
-                               vnewstate = gst_structure_get_value(structure, "new-state");
-                               vpending = gst_structure_get_value(structure, "pending-state");
-                               if (voldstate == NULL || vnewstate == NULL || vpending == NULL)
-                                       break;
-
-                               oldstate = (GstState)voldstate->data[0].v_int;
-                               newstate = (GstState)vnewstate->data[0].v_int;
-                               pending = (GstState)vpending->data[0].v_int;
-
-                               wfd_sink_debug("state changed [%s] : %s--->%s final : %s",
-                                                       GST_OBJECT_NAME(GST_MESSAGE_SRC(msg)),
-                                                       gst_element_state_get_name((GstState)oldstate),
-                                                       gst_element_state_get_name((GstState)newstate),
-                                                       gst_element_state_get_name((GstState)pending));
-
-                               if (oldstate == newstate) {
-                                       wfd_sink_debug("pipeline reports state transition to old state");
-                                       break;
-                               }
+                       wfd_sink_error("warning : %s", error->message);
+                       wfd_sink_error("debug : %s", debug);
 
-                               switch (newstate) {
-                                       case GST_STATE_VOID_PENDING:
-                                       case GST_STATE_NULL:
-                                       case GST_STATE_READY:
-                                       case GST_STATE_PAUSED:
-                                       case GST_STATE_PLAYING:
-                                       default:
-                                               break;
-                               }
+                       MMWFDSINK_FREEIF(debug);
+                       g_error_free(error);
+               }
+               break;
+
+       case GST_MESSAGE_STATE_CHANGED: {
+                       const GValue *voldstate, *vnewstate, *vpending;
+                       GstState oldstate, newstate, pending;
+                       const GstStructure *structure;
+
+                       /* get state info from msg */
+                       structure = gst_message_get_structure(msg);
+                       if (structure == NULL)
+                               break;
+
+                       voldstate = gst_structure_get_value(structure, "old-state");
+                       vnewstate = gst_structure_get_value(structure, "new-state");
+                       vpending = gst_structure_get_value(structure, "pending-state");
+                       if (voldstate == NULL || vnewstate == NULL || vpending == NULL)
+                               break;
+
+                       oldstate = (GstState)voldstate->data[0].v_int;
+                       newstate = (GstState)vnewstate->data[0].v_int;
+                       pending = (GstState)vpending->data[0].v_int;
+
+                       wfd_sink_debug("state changed [%s] : %s--->%s final : %s",
+                                               GST_OBJECT_NAME(GST_MESSAGE_SRC(msg)),
+                                               gst_element_state_get_name((GstState)oldstate),
+                                               gst_element_state_get_name((GstState)newstate),
+                                               gst_element_state_get_name((GstState)pending));
+
+                       /* we only handle messages from pipeline */
+                       if (msg->src != (GstObject *)wfd_sink->pipeline->mainbin[WFD_SINK_M_PIPE].gst)
+                               break;
+
+                       if (oldstate == newstate) {
+                               wfd_sink_debug("pipeline reports state transition to old state");
+                               break;
                        }
-                       break;
 
-               case GST_MESSAGE_CLOCK_LOST: {
-                               GstClock *clock = NULL;
-                               gst_message_parse_clock_lost(msg, &clock);
-                               wfd_sink_debug("The current clock[%s] as selected by the pipeline became unusable.", (clock ? GST_OBJECT_NAME(clock) : "NULL"));
+                       switch (newstate) {
+                       case GST_STATE_VOID_PENDING:
+                       case GST_STATE_NULL:
+                       case GST_STATE_READY:
+                       case GST_STATE_PAUSED:
+                       case GST_STATE_PLAYING:
+                       default:
+                               break;
                        }
-                       break;
+               }
+               break;
 
-               case GST_MESSAGE_NEW_CLOCK: {
-                               GstClock *clock = NULL;
-                               gst_message_parse_new_clock(msg, &clock);
-                               if (!clock)
-                                       break;
-
-                               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)));
-                                       else
-                                               wfd_sink_debug("same clock is selected again! [%s]",
-                                                               GST_STR_NULL(GST_OBJECT_NAME(clock)));
-                               } else {
-                                       wfd_sink_debug("new clock [%s] was selected in the pipeline",
+       case GST_MESSAGE_CLOCK_LOST: {
+                       GstClock *clock = NULL;
+                       gst_message_parse_clock_lost(msg, &clock);
+                       wfd_sink_debug("The current clock[%s] as selected by the pipeline became unusable.",
+                                       (clock ? GST_OBJECT_NAME(clock) : "NULL"));
+               }
+               break;
+
+       case GST_MESSAGE_NEW_CLOCK: {
+                       GstClock *clock = NULL;
+                       gst_message_parse_new_clock(msg, &clock);
+                       if (!clock)
+                               break;
+
+                       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)));
+                               else
+                                       wfd_sink_debug("same clock is selected again! [%s]",
+                                                                       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))));
-                               }
-
-                               wfd_sink->clock = clock;
                        }
-                       break;
 
-               case GST_MESSAGE_APPLICATION: {
-                               const gchar *message_structure_name;
+                       wfd_sink->clock = clock;
+               }
+               break;
 
-                               message_structure_name = gst_structure_get_name(message_structure);
-                               if (!message_structure_name)
-                                       break;
+       case GST_MESSAGE_APPLICATION: {
+                       const gchar *message_structure_name;
 
-                               wfd_sink_debug("message name : %s", GST_STR_NULL(message_structure_name));
-                       }
-                       break;
+                       message_structure_name = gst_structure_get_name(message_structure);
+                       if (!message_structure_name)
+                               break;
 
-               case GST_MESSAGE_ELEMENT: {
-                               const gchar *structure_name = NULL;
-
-                               structure_name = gst_structure_get_name(message_structure);
-                               if (structure_name) {
-                                       wfd_sink_debug("got element specific message[%s]", GST_STR_NULL(structure_name));
-                                       if (g_strrstr(structure_name, "GstUDPSrcTimeout")) {
-                                               wfd_sink_error("Got %s, post error message", GST_STR_NULL(structure_name));
-                                               MMWFDSINK_POST_MESSAGE(wfd_sink,
-                                                                                               MM_ERROR_WFD_INTERNAL,
-                                                                                               MMWFDSINK_CURRENT_STATE(wfd_sink));
-                                       } else if (g_strrstr(structure_name, "GstWFDSrcSessionTimeout")) {
-                                               wfd_sink_error("Got %s, post error message", GST_STR_NULL(structure_name));
-                                               MMWFDSINK_POST_MESSAGE(wfd_sink,
-                                                                                               MM_ERROR_WFD_INTERNAL,
-                                                                                               MMWFDSINK_CURRENT_STATE(wfd_sink));
-                                       }
+                       wfd_sink_debug("message name : %s", GST_STR_NULL(message_structure_name));
+               }
+               break;
+
+       case GST_MESSAGE_ELEMENT: {
+                       const gchar *structure_name = NULL;
+
+                       structure_name = gst_structure_get_name(message_structure);
+                       if (structure_name) {
+                               wfd_sink_debug("got element specific message[%s]", GST_STR_NULL(structure_name));
+                               if (g_strrstr(structure_name, "GstUDPSrcTimeout")) {
+                                       wfd_sink_error("Got %s, post error message", GST_STR_NULL(structure_name));
+                                                                       MMWFDSINK_POST_MESSAGE(wfd_sink,
+                                                                       MM_ERROR_WFD_INTERNAL,
+                                                                       MMWFDSINK_CURRENT_STATE(wfd_sink));
+                               } else if (g_strrstr(structure_name, "GstWFDSessionTimeout")) {
+                                       wfd_sink_error("Got %s, post error message", GST_STR_NULL(structure_name));
+                                       MMWFDSINK_POST_MESSAGE(wfd_sink,
+                                                                       MM_ERROR_WFD_INTERNAL,
+                                                                       MM_WFD_SINK_STATE_DISCONNECTED);
                                }
                        }
-                       break;
-
-               case GST_MESSAGE_PROGRESS: {
-                               GstProgressType type = GST_PROGRESS_TYPE_ERROR;
-                               gchar *category = NULL, *text = NULL;
-
-                               gst_message_parse_progress(msg, &type, &category, &text);
-                               wfd_sink_debug("%s : %s ", GST_STR_NULL(category), GST_STR_NULL(text));
-
-                               switch (type) {
-                                       case GST_PROGRESS_TYPE_START:
-                                               break;
-                                       case GST_PROGRESS_TYPE_COMPLETE:
-                                               if (category && !strcmp(category, "open"))
-                                                       __mm_wfd_sink_set_state(wfd_sink,  MM_WFD_SINK_STATE_CONNECTED);
-                                               else if (category && !strcmp(category, "play")) {
-                                                       __mm_wfd_sink_set_state(wfd_sink,  MM_WFD_SINK_STATE_PLAYING);
-                                                       /*_mm_wfd_sink_correct_pipeline_latency (wfd_sink); */
-                                               } else if (category && !strcmp(category, "pause"))
-                                                       __mm_wfd_sink_set_state(wfd_sink,  MM_WFD_SINK_STATE_PAUSED);
-                                               else if (category && !strcmp(category, "close"))
-                                                       __mm_wfd_sink_set_state(wfd_sink,  MM_WFD_SINK_STATE_DISCONNECTED);
-                                               break;
-                                       case GST_PROGRESS_TYPE_CANCELED:
-                                               break;
-                                       case GST_PROGRESS_TYPE_ERROR:
-                                               if (category && !strcmp(category, "open")) {
-                                                       wfd_sink_error("got error : %s", GST_STR_NULL(text));
-                                                       /*_mm_wfd_sink_disconnect (wfd_sink); */
-                                                       MMWFDSINK_POST_MESSAGE(wfd_sink,
-                                                                                       MM_ERROR_WFD_INTERNAL,
-                                                                                       MMWFDSINK_CURRENT_STATE(wfd_sink));
-                                               } else if (category && !strcmp(category, "play")) {
-                                                       wfd_sink_error("got error : %s", GST_STR_NULL(text));
-                                                       /*_mm_wfd_sink_disconnect (wfd_sink); */
-                                                       MMWFDSINK_POST_MESSAGE(wfd_sink,
-                                                                                       MM_ERROR_WFD_INTERNAL,
-                                                                                       MMWFDSINK_CURRENT_STATE(wfd_sink));
-                                               } else if (category && !strcmp(category, "pause")) {
-                                                       wfd_sink_error("got error : %s", GST_STR_NULL(text));
-                                                       /*_mm_wfd_sink_disconnect (wfd_sink); */
+               }
+               break;
+
+       case GST_MESSAGE_PROGRESS: {
+                       GstProgressType type = GST_PROGRESS_TYPE_ERROR;
+                       gchar *category = NULL, *text = NULL;
+
+                       gst_message_parse_progress(msg, &type, &category, &text);
+                       wfd_sink_debug("%s : %s ", GST_STR_NULL(category), GST_STR_NULL(text));
+
+                       switch (type) {
+                       case GST_PROGRESS_TYPE_START:
+                               break;
+                       case GST_PROGRESS_TYPE_COMPLETE:
+                               if (category && !strcmp(category, "open")) {
+                                       __mm_wfd_sink_set_state(wfd_sink,  MM_WFD_SINK_STATE_CONNECTED);
+                               } else if (category && !strcmp(category, "play")) {
+                                       __mm_wfd_sink_set_state(wfd_sink,  MM_WFD_SINK_STATE_PLAYING);
+                                       /*_mm_wfd_sink_correct_pipeline_latency (wfd_sink); */
+                               } else if (category && !strcmp(category, "pause")) {
+                                       __mm_wfd_sink_set_state(wfd_sink,  MM_WFD_SINK_STATE_PAUSED);
+                               } else if (category && !strcmp(category, "close")) {
+                                       __mm_wfd_sink_set_state(wfd_sink,  MM_WFD_SINK_STATE_DISCONNECTED);
+                               }
+                               break;
+                       case GST_PROGRESS_TYPE_CANCELED:
+                               break;
+                       case GST_PROGRESS_TYPE_ERROR:
+                               if (category && !strcmp(category, "open")) {
+                                       wfd_sink_error("got error : %s", GST_STR_NULL(text));
+                                       /*_mm_wfd_sink_disconnect (wfd_sink); */
+                                       MMWFDSINK_POST_MESSAGE(wfd_sink,
+                                                       MM_ERROR_WFD_INTERNAL,
+                                                       MMWFDSINK_CURRENT_STATE(wfd_sink));
+                               } else if (category && !strcmp(category, "play")) {
+                                       wfd_sink_error("got error : %s", GST_STR_NULL(text));
+                                       /*_mm_wfd_sink_disconnect (wfd_sink); */
+                                       MMWFDSINK_POST_MESSAGE(wfd_sink,
+                                                               MM_ERROR_WFD_INTERNAL,
+                                                               MMWFDSINK_CURRENT_STATE(wfd_sink));
+                               } else if (category && !strcmp(category, "pause")) {
+                                       wfd_sink_error("got error : %s", GST_STR_NULL(text));
+                                       /*_mm_wfd_sink_disconnect (wfd_sink); */
                                                        MMWFDSINK_POST_MESSAGE(wfd_sink,
-                                                                                       MM_ERROR_WFD_INTERNAL,
-                                                                                       MMWFDSINK_CURRENT_STATE(wfd_sink));
-                                               } else if (category && !strcmp(category, "close")) {
-                                                       wfd_sink_error("got error : %s", GST_STR_NULL(text));
+                                                       MM_ERROR_WFD_INTERNAL,
+                                                       MMWFDSINK_CURRENT_STATE(wfd_sink));
+                               } else if (category && !strcmp(category, "close")) {
+                                       wfd_sink_error("got error : %s", GST_STR_NULL(text));
                                                        /*_mm_wfd_sink_disconnect (wfd_sink); */
                                                        MMWFDSINK_POST_MESSAGE(wfd_sink,
-                                                                                       MM_ERROR_WFD_INTERNAL,
-                                                                                       MMWFDSINK_CURRENT_STATE(wfd_sink));
-                                               } else {
-                                                       wfd_sink_error("got error : %s", GST_STR_NULL(text));
-                                               }
-                                               break;
-                                       default:
-                                               wfd_sink_error("progress message has no type");
-                                               return ret;
+                                                       MM_ERROR_WFD_INTERNAL,
+                                                       MMWFDSINK_CURRENT_STATE(wfd_sink));
+                               } else {
+                                       wfd_sink_error("got error : %s", GST_STR_NULL(text));
                                }
-
-                               MMWFDSINK_FREEIF(category);
-                               MMWFDSINK_FREEIF(text);
+                               break;
+                       default:
+                               wfd_sink_error("progress message has no type");
+                               return ret;
                        }
-                       break;
-               case GST_MESSAGE_ASYNC_START:
-                       wfd_sink_debug("GST_MESSAGE_ASYNC_START : %s", gst_element_get_name(GST_MESSAGE_SRC(msg)));
-                       break;
-               case GST_MESSAGE_ASYNC_DONE:
-                       wfd_sink_debug("GST_MESSAGE_ASYNC_DONE : %s", gst_element_get_name(GST_MESSAGE_SRC(msg)));
-                       break;
-               case GST_MESSAGE_UNKNOWN:
-               case GST_MESSAGE_INFO:
-               case GST_MESSAGE_TAG:
-               case GST_MESSAGE_BUFFERING:
-               case GST_MESSAGE_EOS:
-               case GST_MESSAGE_STATE_DIRTY:
-               case GST_MESSAGE_STEP_DONE:
-               case GST_MESSAGE_CLOCK_PROVIDE:
-               case GST_MESSAGE_STRUCTURE_CHANGE:
-               case GST_MESSAGE_STREAM_STATUS:
-               case GST_MESSAGE_SEGMENT_START:
-               case GST_MESSAGE_SEGMENT_DONE:
-               case GST_MESSAGE_DURATION:
-               case GST_MESSAGE_LATENCY:
-               case GST_MESSAGE_REQUEST_STATE:
-               case GST_MESSAGE_STEP_START:
-               case GST_MESSAGE_QOS:
-               case GST_MESSAGE_ANY:
-                       break;
-               default:
-                       wfd_sink_debug("unhandled message");
-                       break;
+
+                       MMWFDSINK_FREEIF(category);
+                       MMWFDSINK_FREEIF(text);
+               }
+               break;
+
+       case GST_MESSAGE_ASYNC_START:
+               wfd_sink_debug("GST_MESSAGE_ASYNC_START : %s", gst_element_get_name(GST_MESSAGE_SRC(msg)));
+               break;
+       case GST_MESSAGE_ASYNC_DONE:
+               wfd_sink_debug("GST_MESSAGE_ASYNC_DONE : %s", gst_element_get_name(GST_MESSAGE_SRC(msg)));
+               break;
+       case GST_MESSAGE_UNKNOWN:
+       case GST_MESSAGE_INFO:
+       case GST_MESSAGE_TAG:
+       case GST_MESSAGE_BUFFERING:
+       case GST_MESSAGE_EOS:
+       case GST_MESSAGE_STATE_DIRTY:
+       case GST_MESSAGE_STEP_DONE:
+       case GST_MESSAGE_CLOCK_PROVIDE:
+       case GST_MESSAGE_STRUCTURE_CHANGE:
+       case GST_MESSAGE_STREAM_STATUS:
+       case GST_MESSAGE_SEGMENT_START:
+       case GST_MESSAGE_SEGMENT_DONE:
+       case GST_MESSAGE_DURATION:
+       case GST_MESSAGE_LATENCY:
+       case GST_MESSAGE_REQUEST_STATE:
+       case GST_MESSAGE_STEP_START:
+       case GST_MESSAGE_QOS:
+       case GST_MESSAGE_ANY:
+               break;
+       default:
+               wfd_sink_debug("unhandled message");
+               break;
        }
 
        return ret;
 }
 
-static int
+int
 __mm_wfd_sink_gst_element_add_bucket_to_bin(GstBin *bin, GList *element_bucket, gboolean need_prepare)
 {
        GList *bucket = element_bucket;
@@ -822,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++;
                }
@@ -840,7 +1073,7 @@ __mm_wfd_sink_gst_element_add_bucket_to_bin(GstBin *bin, GList *element_bucket,
        return successful_add_count;
 }
 
-static int
+int
 __mm_wfd_sink_gst_element_link_bucket(GList *element_bucket)
 {
        GList *bucket = element_bucket;
@@ -861,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;
                        }
                }
@@ -880,7 +1113,7 @@ __mm_wfd_sink_gst_element_link_bucket(GList *element_bucket)
        return successful_link_count;
 }
 
-static int
+int
 __mm_wfd_sink_check_state(mm_wfd_sink_t *wfd_sink, MMWFDSinkCommandType cmd)
 {
        MMWFDSinkStateType cur_state = MM_WFD_SINK_STATE_NONE;
@@ -894,98 +1127,89 @@ __mm_wfd_sink_check_state(mm_wfd_sink_t *wfd_sink, MMWFDSinkCommandType cmd)
        cur_state = MMWFDSINK_CURRENT_STATE(wfd_sink);
 
        switch (cmd) {
-               case MM_WFD_SINK_COMMAND_CREATE: {
-                               if (cur_state != MM_WFD_SINK_STATE_NONE)
-                                       goto invalid_state;
-
-                               MMWFDSINK_PENDING_STATE(wfd_sink) = MM_WFD_SINK_STATE_NULL;
-                       }
-                       break;
-
-               case MM_WFD_SINK_COMMAND_PREPARE: {
-                               if (cur_state == MM_WFD_SINK_STATE_PREPARED)
-                                       goto no_operation;
-                               else if (cur_state != MM_WFD_SINK_STATE_NULL)
-                                       goto invalid_state;
+       case MM_WFD_SINK_COMMAND_CREATE:
+               if (cur_state != MM_WFD_SINK_STATE_NONE)
+                       goto invalid_state;
+
+               MMWFDSINK_PENDING_STATE(wfd_sink) = MM_WFD_SINK_STATE_NULL;
+               break;
+
+       case MM_WFD_SINK_COMMAND_PREPARE:
+               if (cur_state == MM_WFD_SINK_STATE_PREPARED)
+                       goto no_operation;
+               else if (cur_state != MM_WFD_SINK_STATE_NULL)
+                       goto invalid_state;
+
+               MMWFDSINK_PENDING_STATE(wfd_sink) = MM_WFD_SINK_STATE_PREPARED;
+               break;
+
+       case MM_WFD_SINK_COMMAND_CONNECT:
+               if (cur_state == MM_WFD_SINK_STATE_CONNECTED)
+                       goto no_operation;
+               else if (cur_state != MM_WFD_SINK_STATE_PREPARED)
+                       goto invalid_state;
+
+               MMWFDSINK_PENDING_STATE(wfd_sink) = MM_WFD_SINK_STATE_CONNECTED;
+               break;
+
+       case MM_WFD_SINK_COMMAND_START:
+               if (cur_state == MM_WFD_SINK_STATE_PLAYING)
+                       goto no_operation;
+               else if (cur_state != MM_WFD_SINK_STATE_CONNECTED)
+                       goto invalid_state;
+
+               MMWFDSINK_PENDING_STATE(wfd_sink) = MM_WFD_SINK_STATE_PLAYING;
+               break;
+
+       case MM_WFD_SINK_COMMAND_PAUSE:
+               if (cur_state == MM_WFD_SINK_STATE_PAUSED)
+                       goto no_operation;
+               else if (cur_state != MM_WFD_SINK_STATE_PLAYING)
+                       goto invalid_state;
+
+               MMWFDSINK_PENDING_STATE(wfd_sink) = MM_WFD_SINK_STATE_PAUSED;
+               break;
+
+       case MM_WFD_SINK_COMMAND_RESUME:
+               if (cur_state == MM_WFD_SINK_STATE_PLAYING)
+                       goto no_operation;
+               else if (cur_state != MM_WFD_SINK_STATE_PAUSED)
+                       goto invalid_state;
+
+               MMWFDSINK_PENDING_STATE(wfd_sink) = MM_WFD_SINK_STATE_PLAYING;
+               break;
+
+       case MM_WFD_SINK_COMMAND_DISCONNECT:
+               if (cur_state == MM_WFD_SINK_STATE_NONE ||
+                   cur_state == MM_WFD_SINK_STATE_NULL ||
+                   cur_state == MM_WFD_SINK_STATE_PREPARED ||
+                   cur_state == MM_WFD_SINK_STATE_DISCONNECTED)
+                       goto no_operation;
+               else if (cur_state != MM_WFD_SINK_STATE_PLAYING &&
+                       cur_state != MM_WFD_SINK_STATE_CONNECTED &&
+                       cur_state != MM_WFD_SINK_STATE_PAUSED)
+                       goto invalid_state;
+
+               MMWFDSINK_PENDING_STATE(wfd_sink) = MM_WFD_SINK_STATE_DISCONNECTED;
+               break;
+
+       case MM_WFD_SINK_COMMAND_UNPREPARE:
+               if (cur_state == MM_WFD_SINK_STATE_NONE ||
+                   cur_state == MM_WFD_SINK_STATE_NULL)
+                       goto no_operation;
+
+               MMWFDSINK_PENDING_STATE(wfd_sink) = MM_WFD_SINK_STATE_NULL;
+               break;
+
+       case MM_WFD_SINK_COMMAND_DESTROY:
+               if (cur_state == MM_WFD_SINK_STATE_NONE)
+                       goto no_operation;
 
-                               MMWFDSINK_PENDING_STATE(wfd_sink) = MM_WFD_SINK_STATE_PREPARED;
-                       }
-                       break;
-
-               case MM_WFD_SINK_COMMAND_CONNECT: {
-                               if (cur_state == MM_WFD_SINK_STATE_CONNECTED)
-                                       goto no_operation;
-                               else if (cur_state != MM_WFD_SINK_STATE_PREPARED)
-                                       goto invalid_state;
-
-                               MMWFDSINK_PENDING_STATE(wfd_sink) = MM_WFD_SINK_STATE_CONNECTED;
-                       }
-                       break;
-
-               case MM_WFD_SINK_COMMAND_START: {
-                               if (cur_state == MM_WFD_SINK_STATE_PLAYING)
-                                       goto no_operation;
-                               else if (cur_state != MM_WFD_SINK_STATE_CONNECTED)
-                                       goto invalid_state;
-
-                               MMWFDSINK_PENDING_STATE(wfd_sink) = MM_WFD_SINK_STATE_PLAYING;
-                       }
-                       break;
-
-               case MM_WFD_SINK_COMMAND_PAUSE: {
-                               if (cur_state == MM_WFD_SINK_STATE_PAUSED)
-                                       goto no_operation;
-                               else if (cur_state != MM_WFD_SINK_STATE_PLAYING)
-                                       goto invalid_state;
-
-                               MMWFDSINK_PENDING_STATE(wfd_sink) = MM_WFD_SINK_STATE_PAUSED;
-                       }
-                       break;
-
-               case MM_WFD_SINK_COMMAND_RESUME: {
-                               if (cur_state == MM_WFD_SINK_STATE_PLAYING)
-                                       goto no_operation;
-                               else if (cur_state != MM_WFD_SINK_STATE_PAUSED)
-                                       goto invalid_state;
-
-                               MMWFDSINK_PENDING_STATE(wfd_sink) = MM_WFD_SINK_STATE_PLAYING;
-                       }
-                       break;
-
-               case MM_WFD_SINK_COMMAND_DISCONNECT: {
-                               if (cur_state == MM_WFD_SINK_STATE_NONE ||
-                                   cur_state == MM_WFD_SINK_STATE_NULL ||
-                                   cur_state == MM_WFD_SINK_STATE_PREPARED ||
-                                   cur_state == MM_WFD_SINK_STATE_DISCONNECTED)
-                                       goto no_operation;
-                               else if (cur_state != MM_WFD_SINK_STATE_PLAYING &&
-                                       cur_state != MM_WFD_SINK_STATE_CONNECTED &&
-                                       cur_state != MM_WFD_SINK_STATE_PAUSED)
-                                       goto invalid_state;
-
-                               MMWFDSINK_PENDING_STATE(wfd_sink) = MM_WFD_SINK_STATE_DISCONNECTED;
-                       }
-                       break;
-
-               case MM_WFD_SINK_COMMAND_UNPREPARE: {
-                               if (cur_state == MM_WFD_SINK_STATE_NONE ||
-                                   cur_state == MM_WFD_SINK_STATE_NULL)
-                                       goto no_operation;
-
-                               MMWFDSINK_PENDING_STATE(wfd_sink) = MM_WFD_SINK_STATE_NULL;
-                       }
-                       break;
-
-               case MM_WFD_SINK_COMMAND_DESTROY: {
-                               if (cur_state == MM_WFD_SINK_STATE_NONE)
-                                       goto no_operation;
-
-                               MMWFDSINK_PENDING_STATE(wfd_sink) = MM_WFD_SINK_STATE_NONE;
-                       }
-                       break;
+               MMWFDSINK_PENDING_STATE(wfd_sink) = MM_WFD_SINK_STATE_NONE;
+               break;
 
-               default:
-                       break;
+       default:
+               break;
        }
 
        wfd_sink->cmd = cmd;
@@ -1023,10 +1247,10 @@ static int __mm_wfd_sink_set_state(mm_wfd_sink_t *wfd_sink, MMWFDSinkStateType s
        if (MMWFDSINK_CURRENT_STATE(wfd_sink) == MMWFDSINK_PENDING_STATE(wfd_sink))
                MMWFDSINK_PENDING_STATE(wfd_sink) = MM_WFD_SINK_STATE_NONE;
 
-       /* poset state message to application */
+       /* 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);
@@ -1046,12 +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);
+       wfd_sink_return_val_if_fail(state > GST_STATE_VOID_PENDING,
+                                                               MM_ERROR_WFD_INVALID_ARGUMENT);
 
        wfd_sink_debug("try to set %s state ", gst_element_state_get_name(state));
 
@@ -1064,7 +1289,8 @@ __mm_wfd_sink_set_pipeline_state(mm_wfd_sink_t *wfd_sink, GstState state, gboole
        if (!async) {
                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);
+               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);
                if (result == GST_STATE_CHANGE_FAILURE) {
                        wfd_sink_error("fail to get state within %d seconds....", wfd_sink->ini.state_change_timeout);
 
@@ -1076,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));
        }
 
 
@@ -1095,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);
 
 
@@ -1150,17 +1376,210 @@ _mm_wfd_sink_reset_basetime(mm_wfd_sink_t *wfd_sink)
 }
 
 int
-__mm_wfd_sink_prepare_video_pipeline(mm_wfd_sink_t *wfd_sink)
+__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 *bin = NULL;
+       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) {
@@ -1185,56 +1604,361 @@ __mm_wfd_sink_prepare_video_pipeline(mm_wfd_sink_t *wfd_sink)
                        goto ERROR;
                }
        }
-
-       /* set video decodebin state as READY */
+       /* add video decodebin to pipeline */
        if (wfd_sink->pipeline->v_decodebin && wfd_sink->pipeline->v_decodebin[WFD_SINK_V_D_BIN].gst) {
-               bin = wfd_sink->pipeline->v_decodebin[WFD_SINK_V_D_BIN].gst;
-               if (GST_STATE(bin) <= GST_STATE_NULL) {
-                       if (GST_STATE_CHANGE_FAILURE == gst_element_set_state(bin, GST_STATE_READY)) {
-                               wfd_sink_error("failed to set state(READY) to video decodebin");
+               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....");
        }
 
-       /* set video sinkbin state as READY */
+       /* add video sinkbin to pipeline */
        if (wfd_sink->pipeline->v_sinkbin && wfd_sink->pipeline->v_sinkbin[WFD_SINK_V_S_BIN].gst) {
-               bin = wfd_sink->pipeline->v_sinkbin[WFD_SINK_V_S_BIN].gst;
-               if (GST_STATE(bin) <= GST_STATE_NULL) {
-                       if (GST_STATE_CHANGE_FAILURE == gst_element_set_state(bin, GST_STATE_READY)) {
-                               wfd_sink_error("failed to set state(READY) to video sinkbin");
+               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;
+               }
+
+               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);
+
+       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;
+                       }
+
+                       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;
+               }
+       }
+       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));
+                                                       MM_ERROR_WFD_INTERNAL,
+                                                       MMWFDSINK_CURRENT_STATE(wfd_sink));
 
        return MM_ERROR_WFD_INTERNAL;
 }
 
-int __mm_wfd_sink_prepare_audio_pipeline(mm_wfd_sink_t *wfd_sink)
+int
+__mm_wfd_sink_prepare_audio_pipeline(mm_wfd_sink_t *wfd_sink, GstPad **pad)
 {
-       GstElement *bin  = NULL;
+       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) {
@@ -1260,42 +1984,159 @@ int __mm_wfd_sink_prepare_audio_pipeline(mm_wfd_sink_t *wfd_sink)
                }
        }
 
-       /* 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) {
-               bin  = wfd_sink->pipeline->a_decodebin[WFD_SINK_A_D_BIN].gst;
-               if (GST_STATE(bin) <= GST_STATE_NULL) {
-                       if (GST_STATE_CHANGE_FAILURE == gst_element_set_state(bin, GST_STATE_READY)) {
-                               wfd_sink_error("failed to set state(READY) to audio decodebin");
+               a_decodebin = wfd_sink->pipeline->a_decodebin[WFD_SINK_A_D_BIN].gst;
+
+               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) {
-               bin = wfd_sink->pipeline->a_sinkbin[WFD_SINK_A_S_BIN].gst;
-               if (GST_STATE(bin) <= GST_STATE_NULL) {
-                       if (GST_STATE_CHANGE_FAILURE == gst_element_set_state(bin , GST_STATE_READY)) {
-                               wfd_sink_error("failed to set state(READY) to audio sinkbin");
+               a_sinkbin = wfd_sink->pipeline->a_sinkbin[WFD_SINK_A_S_BIN].gst;
+
+               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;
 }
@@ -1318,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");
@@ -1344,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;
        }
 
@@ -1373,11 +2214,11 @@ _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 "\n", */
+                       /*wfd_sink_debug ("%s :diff time : %" GST_TIME_FORMAT "", */
                        /*      GST_STR_NULL((GST_OBJECT_NAME(pad))), */
                        /*      GST_TIME_ARGS(diff)); */
                }
@@ -1430,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 */
@@ -1453,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 */
@@ -1489,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 */
@@ -1501,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);
@@ -1511,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*/
@@ -1523,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);
        }
 
@@ -1532,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)) {
-                       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)) {
-                       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));
@@ -1625,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");
-               if (!srcpad) {
-                       wfd_sink_error("failed to get src pad from %s",
-                                       GST_STR_NULL(GST_ELEMENT_NAME(decodebin)));
-                       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;
-               }
-
-               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)));
+               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;
                }
 
-               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)));
+               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;
                }
-               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;
        }
 
+       /* take decodebin/sinkbin */
+       if (name[0] == 'v') {
+               wfd_sink_debug("=========== >>>>>>>>>> Received VIDEO 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_video_pipeline(wfd_sink, &sinkpad)) {
+                       wfd_sink_error("failed to prepare video pipeline....");
                        goto ERROR;
                }
-       }
+       } else if (name[0] == 'a') {
+               wfd_sink_debug("=========== >>>>>>>>>> Received AUDIO pad...");
 
-       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)));
+               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;
                }
+       } else {
+               wfd_sink_error("unexceptable pad is added!!!");
+               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') {
@@ -1689,30 +2501,29 @@ __mm_wfd_sink_demux_pad_added(GstElement *ele, GstPad *pad, gpointer data)
                MMWFDSINK_GENERATE_DOT_IF_ENABLED(wfd_sink, "audio-pad-added-pipeline");
        }
 
+done:
        MMWFDSINK_FREEIF(name);
 
+       if (srcpad) {
+               gst_object_unref(GST_OBJECT(srcpad));
+               srcpad = NULL;
+       }
+       if (sinkpad) {
+               gst_object_unref(GST_OBJECT(sinkpad));
+               sinkpad = NULL;
+       }
        wfd_sink_debug_fleave();
 
        return;
 
        /* ERRORS */
 ERROR:
-       MMWFDSINK_FREEIF(name);
-
-       if (srcpad)
-               gst_object_unref(GST_OBJECT(srcpad));
-       srcpad = NULL;
-
-       if (sinkpad)
-               gst_object_unref(GST_OBJECT(sinkpad));
-       sinkpad = NULL;
-
        /* need to notify to app */
        MMWFDSINK_POST_MESSAGE(wfd_sink,
                                                        MM_ERROR_WFD_INTERNAL,
                                                        MMWFDSINK_CURRENT_STATE(wfd_sink));
 
-       return;
+       goto done;
 }
 
 static void
@@ -1745,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;
 
@@ -1757,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"));
@@ -1782,33 +2588,29 @@ __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",
-                                               audio_format,
-                                               stream_info->audio_stream_info.sample_rate,
-                                               stream_info->audio_stream_info.channels,
-                                               stream_info->audio_stream_info.bitwidth);
+                       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);
                }
        }
 
        if (gst_structure_has_field(str, "video_format")) {
                is_valid_video_format = TRUE;
                video_format = g_strdup(gst_structure_get_string(str, "video_format"));
-               if (!g_strrstr(video_format, "H264")) {
+               if (g_strrstr(video_format, "H264")) {
+                       stream_info->video_stream_info.codec = MM_WFD_SINK_VIDEO_CODEC_H264;
+               } else if (g_strrstr(video_format, "H265")) {
+                       stream_info->video_stream_info.codec = MM_WFD_SINK_VIDEO_CODEC_H265;
+               } else {
                        wfd_sink_error("invalid video format(%s)...", video_format);
                        is_valid_video_format = FALSE;
                }
 
                if (is_valid_video_format == TRUE) {
-                       stream_info->video_stream_info.codec = MM_WFD_SINK_VIDEO_CODEC_H264;
-
                        if (gst_structure_has_field(str, "video_width"))
                                gst_structure_get_int(str, "video_width", &stream_info->video_stream_info.width);
                        if (gst_structure_has_field(str, "video_height"))
@@ -1816,19 +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);
                }
        }
 
@@ -1837,8 +2633,8 @@ __mm_wfd_sink_update_stream_info(GstElement *wfdsrc, GstStructure *str, gpointer
        wfd_sink_debug_fleave();
 }
 
-static void __mm_wfd_sink_prepare_video_resolution(gint resolution, guint *CEA_resolution,
-                                                                                               guint *VESA_resolution, guint *HH_resolution)
+static void __mm_wfd_sink_prepare_video_resolution(gint resolution, guint64 *CEA_resolution,
+                                                                                                       guint64 *VESA_resolution, guint64 *HH_resolution)
 {
        if (resolution == MM_WFD_SINK_RESOLUTION_UNKNOWN) return;
 
@@ -1873,11 +2669,13 @@ static int __mm_wfd_sink_prepare_source(mm_wfd_sink_t *wfd_sink, GstElement *wfd
        GstStructure *wfd_audio_codecs = NULL;
        GstStructure *wfd_video_formats = NULL;
        GstStructure *wfd_content_protection = NULL;
+       GstStructure *wfd2_video_formats = NULL;
+       GstStructure *wfd2_audio_codecs = NULL;
        gint hdcp_version = 0;
        gint hdcp_port = 0;
-       guint CEA_resolution = 0;
-       guint VESA_resolution = 0;
-       guint HH_resolution = 0;
+       guint64 CEA_resolution = 0;
+       guint64 VESA_resolution = 0;
+       guint64 HH_resolution = 0;
        GObjectClass *klass;
 
        wfd_sink_debug_fenter();
@@ -1892,12 +2690,8 @@ static int __mm_wfd_sink_prepare_source(mm_wfd_sink_t *wfd_sink, GstElement *wfd
                g_object_set(G_OBJECT(wfdsrc), "enable-pad-probe", wfd_sink->ini.trace_buffers_of_wfdsrc, NULL);
        g_object_set(G_OBJECT(wfdsrc), "udp-buffer-size", 2097152, NULL);
        g_object_set(G_OBJECT(wfdsrc), "latency", wfd_sink->ini.jitter_buffer_latency, NULL);
-       if (g_object_class_find_property(klass, "user-agent"))
-               g_object_set(G_OBJECT(wfdsrc), "user-agent", wfd_sink->ini.user_agent, NULL);
-       if (g_object_class_find_property(klass, "debug")) /* for common wfdsrc */
-               g_object_set(G_OBJECT(wfdsrc), "debug", wfd_sink->ini.dump_rtsp_message, NULL);
-       if (g_object_class_find_property(klass, "dump-rtsp-message"))
-               g_object_set(G_OBJECT(wfdsrc), "dump-rtsp-message", wfd_sink->ini.dump_rtsp_message, NULL);
+       g_object_set(G_OBJECT(wfdsrc), "user-agent", wfd_sink->ini.user_agent, NULL);
+       g_object_set(G_OBJECT(wfdsrc), "dump-rtsp-message", wfd_sink->ini.dump_rtsp_message, NULL);
        if (g_object_class_find_property(klass, "dump-rtp-data"))
                g_object_set(G_OBJECT(wfdsrc), "dump-rtp-data", wfd_sink->ini.dump_rtp_data, NULL);
        if (g_object_class_find_property(klass, "trace-first-buffer"))
@@ -1909,17 +2703,16 @@ 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) {
-               if (g_object_class_find_property(klass, "audio-param")) /* for common wfdsrc */
-                       g_object_set(G_OBJECT(wfdsrc), "audio-param", wfd_audio_codecs, NULL);
-               if (g_object_class_find_property(klass, "wfd-audio-codecs"))
-                       g_object_set(G_OBJECT(wfdsrc), "wfd-audio-codecs", wfd_audio_codecs, NULL);
+               g_object_set(G_OBJECT(wfdsrc), "wfd-audio-codecs", wfd_audio_codecs, NULL);
+               gst_structure_free(wfd_audio_codecs);
+               wfd_audio_codecs = NULL;
        }
 
        /* set video parameter for Wi-Fi Display session negotiation */
@@ -1928,30 +2721,30 @@ 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_UINT, CEA_resolution,
-                                                       "video_vesa_support", G_TYPE_UINT, VESA_resolution,
-                                                       "video_hh_support", G_TYPE_UINT, 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) {
-               if (g_object_class_find_property(klass, "video-param")) /* for common wfdsrc */
-                       g_object_set(G_OBJECT(wfdsrc), "video-param", wfd_video_formats, NULL);
-               if (g_object_class_find_property(klass, "wfd-video-formats"))
-                       g_object_set(G_OBJECT(wfdsrc), "wfd-video-formats", wfd_video_formats, NULL);
+               g_object_set(G_OBJECT(wfdsrc), "wfd-video-formats", wfd_video_formats, NULL);
+               gst_structure_free(wfd_video_formats);
+               wfd_video_formats = NULL;
        }
 
+
        /* set hdcp parameter for Wi-Fi Display session negotiation */
        if (wfd_sink->ini.wfd_content_protection.enable_hdcp) {
                mm_attrs_get_int_by_name(wfd_sink->attrs, "hdcp_version", &hdcp_version);
@@ -1959,21 +2752,102 @@ 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) {
-                       if (g_object_class_find_property(klass, "hdcp-param")) /* for common wfdsrc */
-                               g_object_set(G_OBJECT(wfdsrc), "hdcp-param", wfd_content_protection, NULL);
-                       if (g_object_class_find_property(klass, "wfd-content-protection"))
-                               g_object_set(G_OBJECT(wfdsrc), "wfd-content-protection", wfd_content_protection, NULL);
+                       g_object_set(G_OBJECT(wfdsrc), "wfd-content-protection", wfd_content_protection, NULL);
+                       gst_structure_free(wfd_content_protection);
+                       wfd_content_protection = NULL;
+               }
+       }
+
+       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);
+
+               if (wfd2_audio_codecs) {
+                       g_object_set(G_OBJECT(wfdsrc), "wfd2-audio-codecs", wfd2_audio_codecs, NULL);
+                       gst_structure_free(wfd2_audio_codecs);
+                       wfd2_audio_codecs = NULL;
+               }
+       }
+
+       if (g_object_class_find_property(klass, "wfd2-video-format-h264")) {
+               /* set video parameter for Wi-Fi Display R2 session negotiation */
+               CEA_resolution = wfd_sink->ini.wfd2_video_h264_info.video_cea_support;
+               VESA_resolution = wfd_sink->ini.wfd2_video_h264_info.video_vesa_support;
+               HH_resolution =  wfd_sink->ini.wfd2_video_h264_info.video_hh_support;
+
+               if (wfd_sink->ini.wfd2_video_formats.video_codec & WFD_VIDEO_H264) {
+                       wfd2_video_formats = gst_structure_new("wfd2-video-format-h264",
+                                                                                               "video_codec", G_TYPE_UINT, WFD_VIDEO_H264,
+                                                                                               "video_native_resolution", G_TYPE_UINT, wfd_sink->ini.wfd2_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.wfd2_video_h264_info.video_profile,
+                                                                                               "video_level", G_TYPE_UINT, wfd_sink->ini.wfd2_video_h264_info.video_level,
+                                                                                               "video_latency", G_TYPE_UINT, wfd_sink->ini.wfd2_video_h264_info.video_latency,
+                                                                                               "video_vertical_resolution", G_TYPE_INT, wfd_sink->ini.wfd2_video_h264_info.video_vertical_resolution,
+                                                                                               "video_horizontal_resolution", G_TYPE_INT, wfd_sink->ini.wfd2_video_h264_info.video_horizontal_resolution,
+                                                                                               "video_minimum_slicing", G_TYPE_INT, wfd_sink->ini.wfd2_video_h264_info.video_minimum_slicing,
+                                                                                               "video_slice_enc_param", G_TYPE_INT, wfd_sink->ini.wfd2_video_h264_info.video_slice_enc_param,
+                                                                                               "video_framerate_control_support", G_TYPE_INT, wfd_sink->ini.wfd2_video_h264_info.video_framerate_control_support,
+                                                                                               "video_non_transcoding_support", G_TYPE_INT, wfd_sink->ini.wfd2_video_formats.video_non_transcoding_support,
+                                                                                               NULL);
+
+                       if (wfd2_video_formats) {
+                               g_object_set(G_OBJECT(wfdsrc), "wfd2-video-format-h264", wfd2_video_formats, NULL);
+                               gst_structure_free(wfd2_video_formats);
+                               wfd2_video_formats = NULL;
+                       }
+               }
+       }
+
+       if (g_object_class_find_property(klass, "wfd2-video-format-h265")) {
+               /* set video parameter for Wi-Fi Display R2 session negotiation */
+               CEA_resolution = wfd_sink->ini.wfd2_video_h265_info.video_cea_support;
+               VESA_resolution = wfd_sink->ini.wfd2_video_h265_info.video_vesa_support;
+               HH_resolution =  wfd_sink->ini.wfd2_video_h265_info.video_hh_support;
+
+               if (wfd_sink->ini.wfd2_video_formats.video_codec & WFD_VIDEO_H265) {
+                       wfd2_video_formats = gst_structure_new("wfd2-video-format-h265",
+                                                                                               "video_codec", G_TYPE_UINT, WFD_VIDEO_H265,
+                                                                                               "video_native_resolution", G_TYPE_UINT, wfd_sink->ini.wfd2_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.wfd2_video_h265_info.video_profile,
+                                                                                               "video_level", G_TYPE_UINT, wfd_sink->ini.wfd2_video_h265_info.video_level,
+                                                                                               "video_latency", G_TYPE_UINT, wfd_sink->ini.wfd2_video_h265_info.video_latency,
+                                                                                               "video_vertical_resolution", G_TYPE_INT, wfd_sink->ini.wfd2_video_h265_info.video_vertical_resolution,
+                                                                                               "video_horizontal_resolution", G_TYPE_INT, wfd_sink->ini.wfd2_video_h265_info.video_horizontal_resolution,
+                                                                                               "video_minimum_slicing", G_TYPE_INT, wfd_sink->ini.wfd2_video_h265_info.video_minimum_slicing,
+                                                                                               "video_slice_enc_param", G_TYPE_INT, wfd_sink->ini.wfd2_video_h265_info.video_slice_enc_param,
+                                                                                               "video_framerate_control_support", G_TYPE_INT, wfd_sink->ini.wfd2_video_h265_info.video_framerate_control_support,
+                                                                                               "video_non_transcoding_support", G_TYPE_INT, wfd_sink->ini.wfd2_video_formats.video_non_transcoding_support,
+                                                               NULL);
+
+                       if (wfd2_video_formats) {
+                               g_object_set(G_OBJECT(wfdsrc), "wfd2-video-format-h265", wfd2_video_formats, NULL);
+                               gst_structure_free(wfd2_video_formats);
+                               wfd2_video_formats = NULL;
+                       }
                }
        }
 
-       g_signal_connect(wfdsrc, "update-media-info", G_CALLBACK(__mm_wfd_sink_update_stream_info), wfd_sink);
+       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_signal_connect(wfdsrc, "change-av-format", G_CALLBACK(__mm_wfd_sink_change_av_format), 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);
 
        wfd_sink_debug_fleave();
 
@@ -1987,21 +2861,26 @@ static int __mm_wfd_sink_prepare_demux(mm_wfd_sink_t *wfd_sink, GstElement *demu
        wfd_sink_return_val_if_fail(wfd_sink, MM_ERROR_WFD_NOT_INITIALIZED);
        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_signal_connect(demux, "pad-added",
+                                       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);
+
+       g_object_get(G_OBJECT(queue), "current-level-time", &time, NULL);
 
-       wfd_sink_warning("%s is overrun",
-                                       GST_STR_NULL(GST_ELEMENT_NAME(element)));
+       wfd_sink_warning("%s is overrun(%" GST_TIME_FORMAT")",
+                                               GST_ELEMENT_NAME(queue), GST_TIME_ARGS(time));
 
        wfd_sink_debug_fleave();
 
@@ -2019,7 +2898,8 @@ static void __mm_wfd_sink_prepare_queue(mm_wfd_sink_t *wfd_sink, GstElement *que
        g_object_set(G_OBJECT(queue), "max-size-bytes", 0, NULL);
        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_signal_connect(queue, "overrun",
+                                       G_CALLBACK(__mm_wfd_sink_queue_overrun), wfd_sink);
 
        wfd_sink_debug_fleave();
 
@@ -2088,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");
@@ -2108,13 +2998,15 @@ static int __mm_wfd_sink_create_pipeline(mm_wfd_sink_t *wfd_sink)
        }
 
        /* add bus message callback*/
-       gst_bus_add_watch(bus, (GstBusFunc)_mm_wfd_sink_msg_callback, wfd_sink);
+       wfd_sink->msg_callback_id = gst_bus_add_watch(bus, (GstBusFunc)_mm_wfd_sink_msg_callback, wfd_sink);
 
        /* set sync handler to get tag synchronously */
        gst_bus_set_sync_handler(bus, _mm_wfd_bus_sync_callback, wfd_sink, NULL);
 
        g_list_free(element_bucket);
+       element_bucket = NULL;
        gst_object_unref(GST_OBJECT(bus));
+       bus = NULL;
 
        /* now we have completed mainbin. take it */
        wfd_sink->pipeline->mainbin = mainbin;
@@ -2132,10 +3024,10 @@ CREATE_ERROR:
        element_bucket = NULL;
 
        /* finished */
-       if (bus)
+       if (bus) {
                gst_object_unref(GST_OBJECT(bus));
-       bus = NULL;
-
+               bus = NULL;
+       }
        /* release element which are not added to bin */
        for (i = 1; i < WFD_SINK_M_NUM; i++) {  /* NOTE : skip pipeline */
                if (mainbin != NULL && mainbin[i].gst) {
@@ -2147,13 +3039,16 @@ CREATE_ERROR:
                                mainbin[i].gst = NULL;
                        } else {
                                gst_object_unref(GST_OBJECT(parent));
+                               parent = NULL;
                        }
                }
        }
 
        /* release mainbin with it's childs */
-       if (mainbin != NULL && mainbin[WFD_SINK_M_PIPE].gst)
+       if (mainbin != NULL && mainbin[WFD_SINK_M_PIPE].gst) {
                gst_object_unref(GST_OBJECT(mainbin[WFD_SINK_M_PIPE].gst));
+               mainbin[WFD_SINK_M_PIPE].gst = NULL;
+       }
 
        MMWFDSINK_FREEIF(mainbin);
 
@@ -2171,16 +3066,15 @@ int __mm_wfd_sink_link_audio_decodebin(mm_wfd_sink_t *wfd_sink)
        GstPad *sinkpad = NULL;
        GstPad *srcpad = NULL;
        GstPad *ghostpad = NULL;
-       GList *first_list = NULL;
-       GList *last_list = NULL;
+       GList *list_temp = NULL;
 
        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");
@@ -2200,40 +3094,41 @@ int __mm_wfd_sink_link_audio_decodebin(mm_wfd_sink_t *wfd_sink)
 
        /* check audio codec */
        switch (wfd_sink->stream_info.audio_stream_info.codec) {
-               case MM_WFD_SINK_AUDIO_CODEC_LPCM:
-                       if (a_decodebin[WFD_SINK_A_D_LPCM_CONVERTER].gst)
-                               element_bucket = g_list_append(element_bucket, &a_decodebin[WFD_SINK_A_D_LPCM_CONVERTER]);
-                       if (a_decodebin[WFD_SINK_A_D_LPCM_FILTER].gst) {
-                               GstCaps *caps = NULL;
-                               element_bucket = g_list_append(element_bucket, &a_decodebin[WFD_SINK_A_D_LPCM_FILTER]);
-                               caps = gst_caps_new_simple("audio/x-raw",
-                                                                       "rate", G_TYPE_INT, wfd_sink->stream_info.audio_stream_info.sample_rate,
-                                                                       "channels", G_TYPE_INT, wfd_sink->stream_info.audio_stream_info.channels,
-                                                                       "format", G_TYPE_STRING, "S16BE", NULL);
-
-                               g_object_set(G_OBJECT(a_decodebin[WFD_SINK_A_D_LPCM_CONVERTER].gst), "caps", caps, NULL);
-                               gst_object_unref(GST_OBJECT(caps));
-                       }
-                       break;
-
-               case MM_WFD_SINK_AUDIO_CODEC_AAC:
-                       if (a_decodebin[WFD_SINK_A_D_AAC_PARSE].gst)
-                               element_bucket = g_list_append(element_bucket, &a_decodebin[WFD_SINK_A_D_AAC_PARSE]);
-                       if (a_decodebin[WFD_SINK_A_D_AAC_DEC].gst)
-                               element_bucket = g_list_append(element_bucket, &a_decodebin[WFD_SINK_A_D_AAC_DEC]);
-                       break;
-
-               case MM_WFD_SINK_AUDIO_CODEC_AC3:
-                       if (a_decodebin[WFD_SINK_A_D_AC3_PARSE].gst)
-                               element_bucket = g_list_append(element_bucket, &a_decodebin[WFD_SINK_A_D_AC3_PARSE]);
-                       if (a_decodebin[WFD_SINK_A_D_AC3_DEC].gst)
-                               element_bucket = g_list_append(element_bucket, &a_decodebin[WFD_SINK_A_D_AC3_DEC]);
-                       break;
-
-               default:
-                       wfd_sink_error("audio codec is not decied yet. cannot link audio decodebin...");
-                       return MM_ERROR_WFD_INTERNAL;
-                       break;
+       case MM_WFD_SINK_AUDIO_CODEC_LPCM:
+               if (a_decodebin[WFD_SINK_A_D_LPCM_CONVERTER].gst)
+                       element_bucket = g_list_append(element_bucket, &a_decodebin[WFD_SINK_A_D_LPCM_CONVERTER]);
+               if (a_decodebin[WFD_SINK_A_D_LPCM_FILTER].gst) {
+                       GstCaps *caps = NULL;
+                       element_bucket = g_list_append(element_bucket, &a_decodebin[WFD_SINK_A_D_LPCM_FILTER]);
+                       caps = gst_caps_new_simple("audio/x-raw",
+                                               "rate", G_TYPE_INT, wfd_sink->stream_info.audio_stream_info.sample_rate,
+                                               "channels", G_TYPE_INT, wfd_sink->stream_info.audio_stream_info.channels,
+                                               "format", G_TYPE_STRING, "S16BE", NULL);
+
+                       g_object_set(G_OBJECT(a_decodebin[WFD_SINK_A_D_LPCM_CONVERTER].gst), "caps", caps, NULL);
+                       gst_object_unref(GST_OBJECT(caps));
+                       caps = NULL;
+               }
+               break;
+
+       case MM_WFD_SINK_AUDIO_CODEC_AAC:
+               if (a_decodebin[WFD_SINK_A_D_AAC_PARSE].gst)
+                       element_bucket = g_list_append(element_bucket, &a_decodebin[WFD_SINK_A_D_AAC_PARSE]);
+               if (a_decodebin[WFD_SINK_A_D_AAC_DEC].gst)
+                       element_bucket = g_list_append(element_bucket, &a_decodebin[WFD_SINK_A_D_AAC_DEC]);
+               break;
+
+       case MM_WFD_SINK_AUDIO_CODEC_AC3:
+               if (a_decodebin[WFD_SINK_A_D_AC3_PARSE].gst)
+                       element_bucket = g_list_append(element_bucket, &a_decodebin[WFD_SINK_A_D_AC3_PARSE]);
+               if (a_decodebin[WFD_SINK_A_D_AC3_DEC].gst)
+                       element_bucket = g_list_append(element_bucket, &a_decodebin[WFD_SINK_A_D_AC3_DEC]);
+               break;
+
+       default:
+               wfd_sink_error("audio codec is not decied yet. cannot link audio decodebin...");
+               return MM_ERROR_WFD_INTERNAL;
+               break;
        }
 
        if (element_bucket == NULL) {
@@ -2258,13 +3153,13 @@ int __mm_wfd_sink_link_audio_decodebin(mm_wfd_sink_t *wfd_sink)
        }
 
        /* get first element's sinkpad for creating ghostpad */
-       first_list = g_list_first(element_bucket);
-       if (first_list == NULL) {
+       list_temp = g_list_first(element_bucket);
+       if (list_temp == NULL) {
                wfd_sink_error("failed to get first list of the element_bucket");
                goto fail_to_link;
        }
 
-       first_element = (MMWFDSinkGstElement *)first_list->data;
+       first_element = (MMWFDSinkGstElement *)list_temp->data;
        if (!first_element) {
                wfd_sink_error("failed to get first element of the audio decodebin");
                goto fail_to_link;
@@ -2273,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;
        }
 
@@ -2292,13 +3187,13 @@ int __mm_wfd_sink_link_audio_decodebin(mm_wfd_sink_t *wfd_sink)
 
 
        /* get last element's src for creating ghostpad */
-       last_list = g_list_last(element_bucket);
-       if (last_list == NULL) {
+       list_temp = g_list_last(element_bucket);
+       if (list_temp == NULL) {
                wfd_sink_error("failed to get last list of the element_bucket");
                goto fail_to_link;
        }
 
-       last_element = (MMWFDSinkGstElement *)last_list->data;
+       last_element = (MMWFDSinkGstElement *)list_temp->data;
        if (!last_element) {
                wfd_sink_error("failed to get last element of the audio decodebin");
                goto fail_to_link;
@@ -2307,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;
        }
 
@@ -2335,13 +3230,15 @@ done:
 
        /* ERRORS*/
 fail_to_link:
-       if (srcpad)
+       if (srcpad) {
                gst_object_unref(GST_OBJECT(srcpad));
-       srcpad = NULL;
+               srcpad = NULL;
+       }
 
-       if (sinkpad)
+       if (sinkpad) {
                gst_object_unref(GST_OBJECT(sinkpad));
-       sinkpad = NULL;
+               sinkpad = NULL;
+       }
 
        g_list_free(element_bucket);
 
@@ -2406,28 +3303,32 @@ 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("unref %s(current ref %d)",
-                                                       GST_STR_NULL(GST_ELEMENT_NAME(a_decodebin[i].gst)),
-                                                       ((GObject *) a_decodebin[i].gst)->ref_count);
+                                       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_object_unref(GST_OBJECT(parent));
+                                       parent = NULL;
                                }
                        }
                }
 
                /* release audio decodebin with it's childs */
-               if (a_decodebin[WFD_SINK_A_D_BIN].gst)
+               if (a_decodebin[WFD_SINK_A_D_BIN].gst) {
                        gst_object_unref(GST_OBJECT(a_decodebin[WFD_SINK_A_D_BIN].gst));
+                       a_decodebin[WFD_SINK_A_D_BIN].gst = NULL;
+               }
 
        } 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;
        }
 
        wfd_sink->audio_decodebin_is_linked = FALSE;
@@ -2439,7 +3340,7 @@ static int  __mm_wfd_sink_destroy_audio_decodebin(mm_wfd_sink_t *wfd_sink)
        return MM_ERROR_NONE;
 }
 
-static int __mm_wfd_sink_create_audio_decodebin(mm_wfd_sink_t *wfd_sink)
+int __mm_wfd_sink_create_audio_decodebin(mm_wfd_sink_t *wfd_sink)
 {
        MMWFDSinkGstElement *a_decodebin = NULL;
        gint audio_codec = WFD_AUDIO_UNKNOWN;
@@ -2450,29 +3351,34 @@ static 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.");
+               return MM_ERROR_NONE;
+       }
 
        /* check audio decodebin could be linked now */
        switch (wfd_sink->stream_info.audio_stream_info.codec) {
-               case MM_WFD_SINK_AUDIO_CODEC_AAC:
-                       audio_codec = WFD_AUDIO_AAC;
-                       link = TRUE;
-                       break;
-               case MM_WFD_SINK_AUDIO_CODEC_AC3:
-                       audio_codec = WFD_AUDIO_AC3;
-                       link = TRUE;
-                       break;
-               case MM_WFD_SINK_AUDIO_CODEC_LPCM:
-                       audio_codec = WFD_AUDIO_LPCM;
-                       link = TRUE;
-                       break;
-               case MM_WFD_SINK_AUDIO_CODEC_NONE:
-               default:
-                       wfd_sink_debug("audio decodebin could NOT be linked now, just create");
-                       audio_codec = wfd_sink->ini.wfd_audio_codecs.audio_codec;
-                       link = FALSE;
-                       break;
+       case MM_WFD_SINK_AUDIO_CODEC_AAC:
+               audio_codec = WFD_AUDIO_AAC;
+               link = TRUE;
+               break;
+       case MM_WFD_SINK_AUDIO_CODEC_AC3:
+               audio_codec = WFD_AUDIO_AC3;
+               link = TRUE;
+               break;
+       case MM_WFD_SINK_AUDIO_CODEC_LPCM:
+               audio_codec = WFD_AUDIO_LPCM;
+               link = TRUE;
+               break;
+       case MM_WFD_SINK_AUDIO_CODEC_NONE:
+       default:
+               wfd_sink_debug("audio decodebin could NOT be linked now, just create");
+               audio_codec = wfd_sink->ini.wfd_audio_codecs.audio_codec;
+               link = FALSE;
+               break;
        }
 
        /* alloc handles */
@@ -2495,12 +3401,14 @@ static 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;
@@ -2574,13 +3482,16 @@ CREATE_ERROR:
                                a_decodebin[i].gst = NULL;
                        } else {
                                gst_object_unref(GST_OBJECT(parent));
+                               parent = NULL;
                        }
                }
        }
 
-       /* release audioo decodebin with it's childs */
-       if (a_decodebin != NULL && a_decodebin[WFD_SINK_A_D_BIN].gst)
+       /* release audio decodebin with it's childs */
+       if (a_decodebin != NULL && a_decodebin[WFD_SINK_A_D_BIN].gst) {
                gst_object_unref(GST_OBJECT(a_decodebin[WFD_SINK_A_D_BIN].gst));
+               a_decodebin[WFD_SINK_A_D_BIN].gst = NULL;
+       }
 
        MMWFDSINK_FREEIF(a_decodebin);
 
@@ -2609,13 +3520,13 @@ static int  __mm_wfd_sink_destroy_audio_sinkbin(mm_wfd_sink_t *wfd_sink)
 
        parent = gst_element_get_parent(a_sinkbin[WFD_SINK_A_S_BIN].gst);
        if (!parent) {
-               wfd_sink_debug("audio decodebin has no parent.. need to relase by itself");
+               wfd_sink_debug("audio sinkbin has no parent.. need to relase by itself");
 
                if (GST_STATE(a_sinkbin[WFD_SINK_A_S_BIN].gst) >= GST_STATE_READY) {
-                       wfd_sink_debug("try to change state of audio decodebin to NULL");
+                       wfd_sink_debug("try to change state of audio sinkbin to NULL");
                        ret = gst_element_set_state(a_sinkbin[WFD_SINK_A_S_BIN].gst, GST_STATE_NULL);
                        if (ret != GST_STATE_CHANGE_SUCCESS) {
-                               wfd_sink_error("failed to change state of audio decodebin to NULL");
+                               wfd_sink_error("failed to change state of audio sinkbin to NULL");
                                return MM_ERROR_WFD_INTERNAL;
                        }
                }
@@ -2626,28 +3537,31 @@ 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("unref %s(current ref %d)",
-                                                       GST_STR_NULL(GST_ELEMENT_NAME(a_sinkbin[i].gst)),
-                                                       ((GObject *) a_sinkbin[i].gst)->ref_count);
+                                       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_object_unref(GST_OBJECT(parent));
+                                       parent = NULL;
                                }
                        }
                }
 
-               /* release audio decodebin with it's childs */
-               if (a_sinkbin[WFD_SINK_A_S_BIN].gst)
+               /* release audio sinkbin with it's childs */
+               if (a_sinkbin[WFD_SINK_A_S_BIN].gst) {
                        gst_object_unref(GST_OBJECT(a_sinkbin[WFD_SINK_A_S_BIN].gst));
-
+                       a_sinkbin[WFD_SINK_A_S_BIN].gst = NULL;
+               }
        } 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;
        }
 
        MMWFDSINK_FREEIF(wfd_sink->pipeline->a_sinkbin);
@@ -2657,7 +3571,7 @@ static int  __mm_wfd_sink_destroy_audio_sinkbin(mm_wfd_sink_t *wfd_sink)
        return MM_ERROR_NONE;
 }
 
-static int __mm_wfd_sink_create_audio_sinkbin(mm_wfd_sink_t *wfd_sink)
+int __mm_wfd_sink_create_audio_sinkbin(mm_wfd_sink_t *wfd_sink)
 {
        MMWFDSinkGstElement *a_sinkbin = NULL;
        MMWFDSinkGstElement *first_element = NULL;
@@ -2665,13 +3579,18 @@ static int __mm_wfd_sink_create_audio_sinkbin(mm_wfd_sink_t *wfd_sink)
        GstPad *ghostpad = NULL;
        GstPad *pad = NULL;
        gint i = 0;
-       GList *first_list = NULL;
+       GList *list_temp = NULL;
 
        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.");
+               return MM_ERROR_NONE;
+       }
 
        /* alloc handles */
        a_sinkbin = (MMWFDSinkGstElement *)g_malloc0(sizeof(MMWFDSinkGstElement) * WFD_SINK_A_S_NUM);
@@ -2691,17 +3610,25 @@ static 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);
+       MMWFDSINK_CREATE_ELEMENT(a_sinkbin, WFD_SINK_A_S_RESAMPLER,
+                                                       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);
+       MMWFDSINK_CREATE_ELEMENT(a_sinkbin, WFD_SINK_A_S_VOLUME,
+                                                       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");
 
+       MMWFDSINK_CREATE_ELEMENT(a_sinkbin, WFD_SINK_A_S_QUEUE,
+                                                       wfd_sink->ini.name_of_audio_sinkbin_queue, "audio_sinkbin_queue", TRUE);
+       MMWFDSINK_PAD_PROBE(wfd_sink, NULL, a_sinkbin[WFD_SINK_A_S_QUEUE].gst,  "sink");
+       MMWFDSINK_PAD_PROBE(wfd_sink, NULL, a_sinkbin[WFD_SINK_A_S_QUEUE].gst,  "src");
+
        /* create sink */
-       MMWFDSINK_CREATE_ELEMENT(a_sinkbin, WFD_SINK_A_S_SINK, wfd_sink->ini.name_of_audio_sink, "audio_sink", TRUE);
+       MMWFDSINK_CREATE_ELEMENT(a_sinkbin, WFD_SINK_A_S_SINK,
+                                                       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)) {
@@ -2723,13 +3650,13 @@ static int __mm_wfd_sink_create_audio_sinkbin(mm_wfd_sink_t *wfd_sink)
        }
 
        /* get first element's of the audio sinkbin */
-       first_list = g_list_first(element_bucket);
-       if (first_list == NULL) {
+       list_temp = g_list_first(element_bucket);
+       if (list_temp == NULL) {
                wfd_sink_error("failed to get first list of the element_bucket");
                goto CREATE_ERROR;
        }
 
-       first_element = (MMWFDSinkGstElement *)first_list->data;
+       first_element = (MMWFDSinkGstElement *)list_temp->data;
        if (!first_element) {
                wfd_sink_error("failed to get first element of the audio sinkbin");
                goto CREATE_ERROR;
@@ -2739,7 +3666,7 @@ static 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;
        }
 
@@ -2754,8 +3681,10 @@ static int __mm_wfd_sink_create_audio_sinkbin(mm_wfd_sink_t *wfd_sink)
                goto CREATE_ERROR;
        }
        gst_object_unref(GST_OBJECT(pad));
+       pad = NULL;
 
        g_list_free(element_bucket);
+       element_bucket = NULL;
 
        /* take it */
        wfd_sink->pipeline->a_sinkbin = a_sinkbin;
@@ -2767,17 +3696,18 @@ static int __mm_wfd_sink_create_audio_sinkbin(mm_wfd_sink_t *wfd_sink)
 CREATE_ERROR:
        wfd_sink_error("failed to create audio sinkbin, releasing all");
 
-       if (pad)
+       if (pad) {
                gst_object_unref(GST_OBJECT(pad));
-       pad = NULL;
-
-       if (ghostpad)
+               pad = NULL;
+       }
+       if (ghostpad) {
                gst_object_unref(GST_OBJECT(ghostpad));
-       ghostpad = NULL;
-
-       if (element_bucket)
+               ghostpad = NULL;
+       }
+       if (element_bucket) {
                g_list_free(element_bucket);
-       element_bucket = NULL;
+               element_bucket = NULL;
+       }
 
        /* release element which are not added to bin */
        for (i = 1; i < WFD_SINK_A_S_NUM; i++) {        /* NOTE : skip bin */
@@ -2790,14 +3720,16 @@ CREATE_ERROR:
                                a_sinkbin[i].gst = NULL;
                        } else {
                                gst_object_unref(GST_OBJECT(parent));
+                               parent = NULL;
                        }
                }
        }
 
        /* release audio sinkbin with it's childs */
-       if (a_sinkbin != NULL && a_sinkbin[WFD_SINK_A_S_BIN].gst)
+       if (a_sinkbin != NULL && a_sinkbin[WFD_SINK_A_S_BIN].gst) {
                gst_object_unref(GST_OBJECT(a_sinkbin[WFD_SINK_A_S_BIN].gst));
-
+               a_sinkbin[WFD_SINK_A_S_BIN].gst = NULL;
+       }
        MMWFDSINK_FREEIF(a_sinkbin);
 
        return MM_ERROR_WFD_INTERNAL;
@@ -2809,19 +3741,18 @@ int __mm_wfd_sink_link_video_decodebin(mm_wfd_sink_t *wfd_sink)
        MMWFDSinkGstElement *first_element = NULL;
        MMWFDSinkGstElement *last_element = NULL;
        GList *element_bucket = NULL;
+       GList *list_temp = NULL;
        GstPad *sinkpad = NULL;
        GstPad *srcpad = NULL;
        GstPad *ghostpad = NULL;
-       GList *first_list = NULL;
-       GList *last_list = NULL;
 
        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");
@@ -2841,28 +3772,24 @@ int __mm_wfd_sink_link_video_decodebin(mm_wfd_sink_t *wfd_sink)
 
        /* check video codec */
        switch (wfd_sink->stream_info.video_stream_info.codec) {
-               case MM_WFD_SINK_VIDEO_CODEC_H264:
-                       if (v_decodebin[WFD_SINK_V_D_H264_PARSE].gst)
-                               element_bucket = g_list_append(element_bucket, &v_decodebin[WFD_SINK_V_D_H264_PARSE]);
-                       if (v_decodebin[WFD_SINK_V_D_CAPSSETTER].gst) {
-                               GstCaps *caps = NULL;
-
-                               element_bucket = g_list_append(element_bucket, &v_decodebin[WFD_SINK_V_D_CAPSSETTER]);
-                               caps = gst_caps_new_simple("video/x-h264",
-                                                                       "width", G_TYPE_INT, wfd_sink->stream_info.video_stream_info.width,
-                                                                       "height", G_TYPE_INT, wfd_sink->stream_info.video_stream_info.height,
-                                                                       "framerate", GST_TYPE_FRACTION, wfd_sink->stream_info.video_stream_info.frame_rate, 1, NULL);
-                               g_object_set(G_OBJECT(v_decodebin[WFD_SINK_V_D_CAPSSETTER].gst), "caps", caps, NULL);
-                               gst_object_unref(GST_OBJECT(caps));
-                       }
-                       if (v_decodebin[WFD_SINK_V_D_H264_DEC].gst)
-                               element_bucket = g_list_append(element_bucket, &v_decodebin[WFD_SINK_V_D_H264_DEC]);
-                       break;
-
-               default:
-                       wfd_sink_error("video codec is not decied yet. cannot link video decpdebin...");
-                       return MM_ERROR_WFD_INTERNAL;
-                       break;
+       case MM_WFD_SINK_VIDEO_CODEC_H264:
+               if (v_decodebin[WFD_SINK_V_D_H264_PARSE].gst)
+                       element_bucket = g_list_append(element_bucket, &v_decodebin[WFD_SINK_V_D_H264_PARSE]);
+               if (v_decodebin[WFD_SINK_V_D_H264_DEC].gst)
+                       element_bucket = g_list_append(element_bucket, &v_decodebin[WFD_SINK_V_D_H264_DEC]);
+               break;
+
+       case MM_WFD_SINK_VIDEO_CODEC_H265:
+               if (v_decodebin[WFD_SINK_V_D_H265_PARSE].gst)
+                       element_bucket = g_list_append(element_bucket, &v_decodebin[WFD_SINK_V_D_H265_PARSE]);
+               if (v_decodebin[WFD_SINK_V_D_H265_DEC].gst)
+                       element_bucket = g_list_append(element_bucket, &v_decodebin[WFD_SINK_V_D_H265_DEC]);
+               break;
+
+       default:
+               wfd_sink_error("video codec is not decied yet. cannot link video decpdebin...");
+               return MM_ERROR_WFD_INTERNAL;
+               break;
        }
 
        if (element_bucket == NULL) {
@@ -2887,13 +3814,13 @@ int __mm_wfd_sink_link_video_decodebin(mm_wfd_sink_t *wfd_sink)
        }
 
        /* get first element's sinkpad for creating ghostpad */
-       first_list = g_list_first(element_bucket);
-       if (first_list == NULL) {
+       list_temp = g_list_first(element_bucket);
+       if (list_temp == NULL) {
                wfd_sink_error("failed to get first list of the element_bucket");
                goto fail_to_link;
        }
 
-       first_element = (MMWFDSinkGstElement *)first_list->data;
+       first_element = (MMWFDSinkGstElement *)list_temp->data;
        if (!first_element) {
                wfd_sink_error("failed to get first element of the video decodebin");
                goto fail_to_link;
@@ -2902,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;
        }
 
@@ -2921,13 +3848,13 @@ int __mm_wfd_sink_link_video_decodebin(mm_wfd_sink_t *wfd_sink)
 
 
        /* get last element's src for creating ghostpad */
-       last_list = g_list_last(element_bucket);
-       if (last_list == NULL) {
+       list_temp = g_list_last(element_bucket);
+       if (list_temp == NULL) {
                wfd_sink_error("failed to get last list of the element_bucket");
                goto fail_to_link;
        }
 
-       last_element = (MMWFDSinkGstElement *)last_list->data;
+       last_element = (MMWFDSinkGstElement *)list_temp->data;
        if (!last_element) {
                wfd_sink_error("failed to get last element of the video decodebin");
                goto fail_to_link;
@@ -2936,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;
        }
 
@@ -2964,16 +3891,20 @@ done:
 
        /* ERRORS*/
 fail_to_link:
-       if (srcpad != NULL)
+       if (srcpad != NULL) {
                gst_object_unref(GST_OBJECT(srcpad));
-       srcpad = NULL;
+               srcpad = NULL;
+       }
 
-       if (sinkpad != NULL)
+       if (sinkpad != NULL) {
                gst_object_unref(GST_OBJECT(sinkpad));
-       sinkpad = NULL;
-
-       g_list_free(element_bucket);
+               sinkpad = NULL;
+       }
 
+       if (element_bucket != NULL) {
+               g_list_free(element_bucket);
+               element_bucket = NULL;
+       }
        return MM_ERROR_WFD_INTERNAL;
 }
 
@@ -3027,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;
@@ -3052,8 +3984,8 @@ static int __mm_wfd_sink_prepare_videosink(mm_wfd_sink_t *wfd_sink, GstElement *
                                        LOGI("Wayland overlay surface type");
                                        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);
+                                       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 = elm_win_wl_window_get(obj);
                                        wl_surface = (struct wl_surface *) ecore_wl_window_surface_get(wl_window);
@@ -3061,30 +3993,35 @@ 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;
-                               }
+                                       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;
 
-                                       if (wl_surface && wl_display){
-                                               wfd_sink_debug ("surface = %p, wl_display = %p", wl_surface, wl_display);
-                                               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;
-                                       }
+                                               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;
+                                               }
+                                       }
                                        wfd_sink_debug("set video param : surface_id %d", wl_surface_id);
-                                       gst_video_overlay_set_window_handle(GST_VIDEO_OVERLAY(video_sink),
-                                               wl_surface_id);
+                                       gst_video_overlay_set_wl_window_wl_surface_id(GST_VIDEO_OVERLAY(video_sink),
+                                                                                                                               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!");
+                                       wfd_sink_debug("display object is NULL!");
                                        return MM_ERROR_WFD_INTERNAL;
                                }
                        }
@@ -3153,30 +4090,34 @@ 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("unref %s(current ref %d)",
-                                                               GST_STR_NULL(GST_ELEMENT_NAME(v_decodebin[i].gst)),
-                                                               ((GObject *) v_decodebin[i].gst)->ref_count);
+                                       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_object_unref(GST_OBJECT(parent));
+                                       parent = NULL;
                                }
                        }
                }
                /* release video decodebin with it's childs */
                if (v_decodebin[WFD_SINK_V_D_BIN].gst) {
-                       gst_object_unref(GST_OBJECT(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;
        }
 
        wfd_sink->video_decodebin_is_linked = FALSE;
@@ -3188,7 +4129,7 @@ static int __mm_wfd_sink_destroy_video_decodebin(mm_wfd_sink_t *wfd_sink)
        return MM_ERROR_NONE;
 }
 
-static int __mm_wfd_sink_create_video_decodebin(mm_wfd_sink_t *wfd_sink)
+int __mm_wfd_sink_create_video_decodebin(mm_wfd_sink_t *wfd_sink)
 {
        MMWFDSinkGstElement *v_decodebin = NULL;
        guint video_codec = WFD_VIDEO_UNKNOWN;
@@ -3199,8 +4140,8 @@ static 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");
@@ -3209,16 +4150,20 @@ static int __mm_wfd_sink_create_video_decodebin(mm_wfd_sink_t *wfd_sink)
 
        /* check video decodebin could be linked now */
        switch (wfd_sink->stream_info.video_stream_info.codec) {
-               case MM_WFD_SINK_VIDEO_CODEC_H264:
-                       video_codec = WFD_VIDEO_H264;
-                       link = TRUE;
-                       break;
-               case MM_WFD_SINK_VIDEO_CODEC_NONE:
-               default:
-                       wfd_sink_debug("video decodebin could NOT be linked now, just create");
-                       video_codec = wfd_sink->ini.wfd_video_formats.video_codec;
-                       link = FALSE;
-                       break;
+       case MM_WFD_SINK_VIDEO_CODEC_H264:
+               video_codec = WFD_VIDEO_H264;
+               link = TRUE;
+               break;
+       case MM_WFD_SINK_VIDEO_CODEC_H265:
+               video_codec = WFD_VIDEO_H265;
+               link = TRUE;
+               break;
+       case MM_WFD_SINK_VIDEO_CODEC_NONE:
+       default:
+               wfd_sink_debug("video decodebin could NOT be linked now, just create");
+               video_codec = wfd_sink->ini.wfd_video_formats.video_codec | wfd_sink->ini.wfd2_video_formats.video_codec;
+               link = FALSE;
+               break;
        }
 
        /* alloc handles */
@@ -3241,6 +4186,7 @@ static 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);
 
@@ -3255,11 +4201,6 @@ static int __mm_wfd_sink_create_video_decodebin(mm_wfd_sink_t *wfd_sink)
                MMWFDSINK_PAD_PROBE(wfd_sink, NULL, v_decodebin[WFD_SINK_V_D_H264_PARSE].gst,  "sink");
                MMWFDSINK_PAD_PROBE(wfd_sink, NULL, v_decodebin[WFD_SINK_V_D_H264_PARSE].gst,  "src");
 
-               /* create capssetter */
-               MMWFDSINK_CREATE_ELEMENT(v_decodebin, WFD_SINK_V_D_CAPSSETTER, wfd_sink->ini.name_of_video_capssetter, "video_capssetter", FALSE);
-               MMWFDSINK_PAD_PROBE(wfd_sink, NULL, v_decodebin[WFD_SINK_V_D_CAPSSETTER].gst,  "sink");
-               MMWFDSINK_PAD_PROBE(wfd_sink, NULL, v_decodebin[WFD_SINK_V_D_CAPSSETTER].gst,  "src");
-
                /* create dec */
                MMWFDSINK_CREATE_ELEMENT(v_decodebin, WFD_SINK_V_D_H264_DEC, wfd_sink->ini.name_of_video_h264_decoder, "video_h264_dec", FALSE);
                MMWFDSINK_PAD_PROBE(wfd_sink, NULL, v_decodebin[WFD_SINK_V_D_H264_DEC].gst,  "sink");
@@ -3272,6 +4213,24 @@ static int __mm_wfd_sink_create_video_decodebin(mm_wfd_sink_t *wfd_sink)
                }
        }
 
+       if (video_codec & WFD_VIDEO_H265) {
+               /* create parser */
+               MMWFDSINK_CREATE_ELEMENT(v_decodebin, WFD_SINK_V_D_H265_PARSE, wfd_sink->ini.name_of_video_h264_parser, "video_h265_parser", FALSE);
+               MMWFDSINK_PAD_PROBE(wfd_sink, NULL, v_decodebin[WFD_SINK_V_D_H265_PARSE].gst,  "sink");
+               MMWFDSINK_PAD_PROBE(wfd_sink, NULL, v_decodebin[WFD_SINK_V_D_H265_PARSE].gst,  "src");
+
+               /* create dec */
+               MMWFDSINK_CREATE_ELEMENT(v_decodebin, WFD_SINK_V_D_H265_DEC, wfd_sink->ini.name_of_video_h265_decoder, "video_h265_dec", FALSE);
+               MMWFDSINK_PAD_PROBE(wfd_sink, NULL, v_decodebin[WFD_SINK_V_D_H265_DEC].gst,  "sink");
+               MMWFDSINK_PAD_PROBE(wfd_sink, NULL, v_decodebin[WFD_SINK_V_D_H265_DEC].gst,  "src");
+               if (v_decodebin[WFD_SINK_V_D_H265_DEC].gst) {
+                       if (MM_ERROR_NONE != __mm_wfd_sink_prepare_videodec(wfd_sink, v_decodebin[WFD_SINK_V_D_H265_DEC].gst)) {
+                               wfd_sink_error("failed to set video decoder property...");
+                               goto CREATE_ERROR;
+                       }
+               }
+       }
+
        g_list_free(element_bucket);
 
        /* take it */
@@ -3307,13 +4266,16 @@ CREATE_ERROR:
                                v_decodebin[i].gst = NULL;
                        } else {
                                gst_object_unref(GST_OBJECT(parent));
+                               parent = NULL;
                        }
                }
        }
 
        /* release video decodebin with it's childs */
-       if (v_decodebin != NULL && v_decodebin[WFD_SINK_V_D_BIN].gst)
+       if (v_decodebin != NULL && v_decodebin[WFD_SINK_V_D_BIN].gst) {
                gst_object_unref(GST_OBJECT(v_decodebin[WFD_SINK_V_D_BIN].gst));
+               v_decodebin[WFD_SINK_V_D_BIN].gst = NULL;
+       }
 
        MMWFDSINK_FREEIF(v_decodebin);
 
@@ -3359,27 +4321,30 @@ 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("unref %s(current ref %d)",
-                                                               GST_STR_NULL(GST_ELEMENT_NAME(v_sinkbin[i].gst)),
-                                                               ((GObject *) v_sinkbin[i].gst)->ref_count);
+                                       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_object_unref(GST_OBJECT(parent));
+                                       parent = NULL;
                                }
                        }
                }
                /* release video sinkbin with it's childs */
                if (v_sinkbin[WFD_SINK_V_S_BIN].gst) {
                        gst_object_unref(GST_OBJECT(v_sinkbin[WFD_SINK_V_S_BIN].gst));
+                       v_sinkbin[WFD_SINK_V_S_BIN].gst = NULL;
                }
        } 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;
        }
 
        MMWFDSINK_FREEIF(wfd_sink->pipeline->v_sinkbin);
@@ -3389,7 +4354,7 @@ static int __mm_wfd_sink_destroy_video_sinkbin(mm_wfd_sink_t *wfd_sink)
        return MM_ERROR_NONE;
 }
 
-static int __mm_wfd_sink_create_video_sinkbin(mm_wfd_sink_t *wfd_sink)
+int __mm_wfd_sink_create_video_sinkbin(mm_wfd_sink_t *wfd_sink)
 {
        MMWFDSinkGstElement *first_element = NULL;
        MMWFDSinkGstElement *v_sinkbin = NULL;
@@ -3402,8 +4367,13 @@ static 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.");
+               return MM_ERROR_NONE;
+       }
 
        /* alloc handles */
        v_sinkbin = (MMWFDSinkGstElement *)g_malloc0(sizeof(MMWFDSinkGstElement) * WFD_SINK_V_S_NUM);
@@ -3436,6 +4406,7 @@ static int __mm_wfd_sink_create_video_sinkbin(mm_wfd_sink_t *wfd_sink)
                caps = gst_caps_new_simple("video/x-raw", "format", G_TYPE_STRING, "SN12", NULL);
                g_object_set(G_OBJECT(v_sinkbin[WFD_SINK_V_S_FILTER].gst), "caps", caps, NULL);
                gst_object_unref(GST_OBJECT(caps));
+               caps = NULL;
        }
 
        /* create sink */
@@ -3480,7 +4451,7 @@ static 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;
        }
 
@@ -3496,9 +4467,10 @@ static int __mm_wfd_sink_create_video_sinkbin(mm_wfd_sink_t *wfd_sink)
        }
 
        gst_object_unref(GST_OBJECT(pad));
+       pad = NULL;
 
        g_list_free(element_bucket);
-
+       element_bucket = NULL;
 
        /* take it */
        wfd_sink->pipeline->v_sinkbin = v_sinkbin;
@@ -3511,15 +4483,20 @@ static int __mm_wfd_sink_create_video_sinkbin(mm_wfd_sink_t *wfd_sink)
 CREATE_ERROR:
        wfd_sink_error("failed to create video sinkbin, releasing all");
 
-       if (pad)
+       if (pad) {
                gst_object_unref(GST_OBJECT(pad));
-       pad = NULL;
+               pad = NULL;
+       }
 
-       if (ghostpad)
+       if (ghostpad) {
                gst_object_unref(GST_OBJECT(ghostpad));
-       ghostpad = NULL;
+               ghostpad = NULL;
+       }
 
-       g_list_free(element_bucket);
+       if (element_bucket) {
+               g_list_free(element_bucket);
+               element_bucket = NULL;
+       }
 
        /* release element which are not added to bin */
        for (i = 1; i < WFD_SINK_V_S_NUM; i++) {        /* NOTE : skip bin */
@@ -3532,14 +4509,16 @@ CREATE_ERROR:
                                v_sinkbin[i].gst = NULL;
                        } else {
                                gst_object_unref(GST_OBJECT(parent));
+                               parent = NULL;
                        }
                }
        }
 
        /* release video sinkbin with it's childs */
-       if (v_sinkbin != NULL && v_sinkbin[WFD_SINK_V_S_BIN].gst)
+       if (v_sinkbin != NULL && v_sinkbin[WFD_SINK_V_S_BIN].gst) {
                gst_object_unref(GST_OBJECT(v_sinkbin[WFD_SINK_V_S_BIN].gst));
-
+               v_sinkbin[WFD_SINK_V_S_BIN].gst = NULL;
+       }
        MMWFDSINK_FREEIF(v_sinkbin);
 
        return MM_ERROR_WFD_INTERNAL;
@@ -3548,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();
 
@@ -3558,12 +4538,31 @@ 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 mainbin to NULL");
+                               wfd_sink_error("failed to change state of pipeline to NULL");
                                return MM_ERROR_WFD_INTERNAL;
+                       } else {
+                               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;
@@ -3585,6 +4584,7 @@ static int __mm_wfd_sink_destroy_pipeline(mm_wfd_sink_t *wfd_sink)
                        }
 
                        gst_object_unref(GST_OBJECT(mainbin[WFD_SINK_M_PIPE].gst));
+                       mainbin[WFD_SINK_M_PIPE].gst = NULL;
 
                        MMWFDSINK_FREEIF(mainbin);
                }
@@ -3592,6 +4592,11 @@ static int __mm_wfd_sink_destroy_pipeline(mm_wfd_sink_t *wfd_sink)
                MMWFDSINK_FREEIF(wfd_sink->pipeline);
        }
 
+       if (wfd_sink->msg_callback_id > 0) {
+               g_source_remove(wfd_sink->msg_callback_id);
+               wfd_sink->msg_callback_id = 0;
+       }
+
        wfd_sink->audio_decodebin_is_linked = FALSE;
        wfd_sink->video_decodebin_is_linked = FALSE;
        wfd_sink->need_to_reset_basetime = FALSE;
@@ -3617,41 +4622,42 @@ __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));
 
        if (iter != NULL) {
                while (!done) {
                        switch (gst_iterator_next(iter, (gpointer)&item)) {
-                               case GST_ITERATOR_OK:
-                                       gst_element_get_state(GST_ELEMENT(item), &state, &pending, time);
-
-                                       factory = gst_element_get_factory(item) ;
-                                       if (factory) {
-                                               wfd_sink_error("%s:%s : From:%s To:%s refcount : %d",
-                                                                       GST_STR_NULL(GST_OBJECT_NAME(factory)),
-                                                                       GST_STR_NULL(GST_ELEMENT_NAME(item)),
-                                                                       gst_element_state_get_name(state),
-                                                                       gst_element_state_get_name(pending),
-                                                                       GST_OBJECT_REFCOUNT_VALUE(item));
-                                       }
-                                       gst_object_unref(item);
-                                       break;
-                               case GST_ITERATOR_RESYNC:
-                                       gst_iterator_resync(iter);
-                                       break;
-                               case GST_ITERATOR_ERROR:
-                                       done = TRUE;
-                                       break;
-                               case GST_ITERATOR_DONE:
-                                       done = TRUE;
-                                       break;
-                               default:
-                                       done = TRUE;
-                                       break;
+                       case GST_ITERATOR_OK:
+                               gst_element_get_state(GST_ELEMENT(item), &state, &pending, time);
+
+                               factory = gst_element_get_factory(item) ;
+                               if (factory) {
+                                       wfd_sink_error("%s:%s : From:%s To:%s refcount : %d",
+                                               GST_STR_NULL(GST_OBJECT_NAME(factory)),
+                                               GST_STR_NULL(GST_ELEMENT_NAME(item)),
+                                               gst_element_state_get_name(state),
+                                               gst_element_state_get_name(pending),
+                                               GST_OBJECT_REFCOUNT_VALUE(item));
+                               }
+                               gst_object_unref(item);
+                               item = NULL;
+                               break;
+                       case GST_ITERATOR_RESYNC:
+                               gst_iterator_resync(iter);
+                               break;
+                       case GST_ITERATOR_ERROR:
+                               done = TRUE;
+                               break;
+                       case GST_ITERATOR_DONE:
+                               done = TRUE;
+                               break;
+                       default:
+                               done = TRUE;
+                               break;
                        }
                }
        }
@@ -3663,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)
@@ -3678,25 +4684,26 @@ __mm_wfd_sink_dump_pipeline_state(mm_wfd_sink_t *wfd_sink)
        return;
 }
 
-const gchar * _mm_wfds_sink_get_state_name(MMWFDSinkStateType state)
+const gchar *
+_mm_wfds_sink_get_state_name(MMWFDSinkStateType state)
 {
        switch (state) {
-               case MM_WFD_SINK_STATE_NONE:
-                       return "NONE";
-               case MM_WFD_SINK_STATE_NULL:
-                       return "NULL";
-               case MM_WFD_SINK_STATE_PREPARED:
-                       return "PREPARED";
-               case MM_WFD_SINK_STATE_CONNECTED:
-                       return "CONNECTED";
-               case MM_WFD_SINK_STATE_PLAYING:
-                       return "PLAYING";
-               case MM_WFD_SINK_STATE_PAUSED:
-                       return "PAUSED";
-               case MM_WFD_SINK_STATE_DISCONNECTED:
-                       return "DISCONNECTED";
-               default:
-                       return "INVAID";
+       case MM_WFD_SINK_STATE_NONE:
+               return "NONE";
+       case MM_WFD_SINK_STATE_NULL:
+               return "NULL";
+       case MM_WFD_SINK_STATE_PREPARED:
+               return "PREPARED";
+       case MM_WFD_SINK_STATE_CONNECTED:
+               return "CONNECTED";
+       case MM_WFD_SINK_STATE_PLAYING:
+               return "PLAYING";
+       case MM_WFD_SINK_STATE_PAUSED:
+               return "PAUSED";
+       case MM_WFD_SINK_STATE_DISCONNECTED:
+               return "DISCONNECTED";
+       default:
+               return "INVAID";
        }
 }
 
@@ -3721,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();
+}