Add unprepare audio/video cmd 81/92481/4
authorSeokHoon Lee <andy.shlee@samsung.com>
Mon, 17 Oct 2016 06:53:30 +0000 (15:53 +0900)
committerSeokHoon Lee <andy.shlee@samsung.com>
Tue, 18 Oct 2016 02:01:58 +0000 (11:01 +0900)
Add PRINT_WFD_REF_COUNT
change SLOG to LOG

Change-Id: I6a1c3567313305b6f1a04505b7c64eade339fead
Signed-off-by: SeokHoon Lee <andy.shlee@samsung.com>
packaging/libmm-wfd.spec
src/include/mm_wfd_sink_dlog.h
src/include/mm_wfd_sink_priv.h
src/mm_wfd_sink_ini.c
src/mm_wfd_sink_manager.c
src/mm_wfd_sink_priv.c

index c8ee919..5079dc4 100644 (file)
@@ -1,6 +1,6 @@
 Name:       libmm-wfd
 Summary:    Multimedia Framework Wifi-Display Library
-Version:    0.2.206
+Version:    0.2.207
 Release:    0
 Group:      System/Libraries
 License:    Apache-2.0
index 958d50e..22b46df 100644 (file)
@@ -38,35 +38,35 @@ extern "C" {
 #define FONT_COLOR_GRAY     "\033[37m"
 
 #define wfd_sink_debug(fmt, arg...) do { \
-       SLOGD(FONT_COLOR_RESET""fmt"", ##arg);     \
+       LOGD(FONT_COLOR_RESET""fmt"", ##arg);     \
        } while (0)
 
 #define wfd_sink_info(fmt, arg...) do { \
-       SLOGI(FONT_COLOR_GREEN""fmt""FONT_COLOR_RESET, ##arg);     \
+       LOGI(FONT_COLOR_GREEN""fmt""FONT_COLOR_RESET, ##arg);     \
        } while (0)
 
 #define wfd_sink_error(fmt, arg...) do { \
-       SLOGE(FONT_COLOR_RED""fmt""FONT_COLOR_RESET, ##arg);     \
+       LOGE(FONT_COLOR_RED""fmt""FONT_COLOR_RESET, ##arg);     \
        } while (0)
 
 #define wfd_sink_warning(fmt, arg...) do { \
-       SLOGW(FONT_COLOR_YELLOW""fmt""FONT_COLOR_RESET, ##arg);     \
+       LOGW(FONT_COLOR_YELLOW""fmt""FONT_COLOR_RESET, ##arg);     \
        } while (0)
 
 #define wfd_sink_debug_fenter() do { \
-       SLOGD(FONT_COLOR_RESET"<Enter>");     \
+       LOGD(FONT_COLOR_RESET"<Enter>");     \
        } while (0)
 
 #define wfd_sink_debug_fleave() do { \
-       SLOGD(FONT_COLOR_RESET"<Leave>");     \
+       LOGD(FONT_COLOR_RESET"<Leave>");     \
        } while (0)
 
 #define wfd_sink_error_fenter() do { \
-       SLOGE(FONT_COLOR_RED"NO-ERROR : <Enter>"FONT_COLOR_RESET);     \
+       LOGE(FONT_COLOR_RED"NO-ERROR : <Enter>"FONT_COLOR_RESET);     \
        } while (0)
 
 #define wfd_sink_error_fleave() do { \
-       SLOGE(FONT_COLOR_RED"NO-ERROR : <Leave>"FONT_COLOR_RESET);     \
+       LOGE(FONT_COLOR_RED"NO-ERROR : <Leave>"FONT_COLOR_RESET);     \
        } while (0)
 
 #define wfd_sink_sucure_info(fmt, arg...) do { \
index 07876ab..eca07d6 100644 (file)
@@ -117,6 +117,8 @@ typedef enum {
        WFD_SINK_MANAGER_CMD_LINK_V_DECODEBIN,
        WFD_SINK_MANAGER_CMD_PREPARE_A_PIPELINE,
        WFD_SINK_MANAGER_CMD_PREPARE_V_PIPELINE,
+       WFD_SINK_MANAGER_CMD_UNPREPARE_A_PIPELINE,
+       WFD_SINK_MANAGER_CMD_UNPREPARE_V_PIPELINE,
        WFD_SINK_MANAGER_CMD_EXIT,
 } WFDSinkManagerCMDType;
 
@@ -260,6 +262,8 @@ int __mm_wfd_sink_link_audio_decodebin(mm_wfd_sink_t *wfd_sink);
 int __mm_wfd_sink_link_video_decodebin(mm_wfd_sink_t *wfd_sink);
 int __mm_wfd_sink_prepare_video_pipeline(mm_wfd_sink_t *wfd_sink, GstPad **sinkpad);
 int __mm_wfd_sink_prepare_audio_pipeline(mm_wfd_sink_t *wfd_sink, GstPad **sinkpad);
+int __mm_wfd_sink_unprepare_audio_pipeline(mm_wfd_sink_t *wfd_sink);
+int __mm_wfd_sink_unprepare_video_pipeline(mm_wfd_sink_t *wfd_sink);
 
 const gchar *_mm_wfds_sink_get_state_name(MMWFDSinkStateType state);
 int __mm_wfd_sink_check_state(mm_wfd_sink_t *wfd_sink, MMWFDSinkCommandType cmd);
@@ -267,6 +271,7 @@ int __mm_wfd_sink_create_audio_decodebin(mm_wfd_sink_t *wfd_sink);
 int __mm_wfd_sink_create_video_decodebin(mm_wfd_sink_t *wfd_sink);
 int __mm_wfd_sink_create_video_sinkbin(mm_wfd_sink_t *wfd_sink);
 int __mm_wfd_sink_create_audio_sinkbin(mm_wfd_sink_t *wfd_sink);
+void __mm_wfd_sink_print_ref_count(mm_wfd_sink_t *wfd_sink);
 int __mm_wfd_sink_gst_element_add_bucket_to_bin(GstBin *bin, GList *element_bucket, gboolean need_prepare);
 int __mm_wfd_sink_gst_element_link_bucket(GList *element_bucket);
 #endif
index a5500f4..3ad0ea2 100644 (file)
@@ -179,7 +179,7 @@ static
 gboolean __generate_sink_default_ini(void)
 {
        int fd = 0;
-       int length;
+       int length = 0;
        const gchar *default_ini = MM_WFD_SINK_DEFAULT_INI;
 
        fd = open(MM_WFD_SINK_INI_DEFAULT_PATH, O_CREAT | O_EXCL, 644);
index b4f9114..a38943a 100644 (file)
@@ -127,18 +127,32 @@ __mm_wfd_sink_manager_thread(gpointer data)
                                break;
                        case WFD_SINK_MANAGER_CMD_PREPARE_A_PIPELINE:
                                wfd_sink_debug("try to prepare audio pipeline.");
-                                       if (MM_ERROR_NONE != __mm_wfd_sink_prepare_audio_pipeline(wfd_sink, NULL)) {
+                               if (MM_ERROR_NONE != __mm_wfd_sink_prepare_audio_pipeline(wfd_sink, NULL)) {
                                        wfd_sink_error("failed to prepare audio pipeline.....");
                                        goto EXIT;
                                }
                                break;
                        case WFD_SINK_MANAGER_CMD_PREPARE_V_PIPELINE:
                                wfd_sink_debug("try to prepare video pipeline.");
-                                       if (MM_ERROR_NONE != __mm_wfd_sink_prepare_video_pipeline(wfd_sink, NULL)) {
+                               if (MM_ERROR_NONE != __mm_wfd_sink_prepare_video_pipeline(wfd_sink, NULL)) {
                                        wfd_sink_error("failed to prepare video pipeline.....");
                                        goto EXIT;
                                }
                                break;
+                       case WFD_SINK_MANAGER_CMD_UNPREPARE_A_PIPELINE:
+                               wfd_sink_debug("try to unprepare audio pipeline.");
+                               if (MM_ERROR_NONE != __mm_wfd_sink_unprepare_audio_pipeline(wfd_sink)) {
+                                       wfd_sink_error("failed to unprepare audio pipeline.....");
+                                       goto EXIT;
+                               }
+                               break;
+                       case WFD_SINK_MANAGER_CMD_UNPREPARE_V_PIPELINE:
+                               wfd_sink_debug("try to unprepare video pipeline.");
+                               if (MM_ERROR_NONE != __mm_wfd_sink_unprepare_video_pipeline(wfd_sink)) {
+                                       wfd_sink_error("failed to unprepare video pipeline.....");
+                                       goto EXIT;
+                               }
+                               break;
                        case WFD_SINK_MANAGER_CMD_EXIT:
                                wfd_sink_debug("exiting manager thread");
                                goto EXIT;
index d6ccfd3..5bf7f0f 100644 (file)
 #include "mm_wfd_sink_enum.h"
 #include "mm_wfd_sink_wayland.h"
 
+#define PRINT_WFD_REF_COUNT(wfd_sink)\
+       do {\
+               wfd_sink_debug("PRINT WFD REF COUNT");\
+               __mm_wfd_sink_print_ref_count(wfd_sink);\
+       } while (0);
+
 /* gstreamer */
 static int __mm_wfd_sink_init_gstreamer(mm_wfd_sink_t *wfd_sink);
 static int __mm_wfd_sink_create_pipeline(mm_wfd_sink_t *wfd_sink);
 static int __mm_wfd_sink_destroy_audio_decodebin(mm_wfd_sink_t *wfd_sink);
 static int __mm_wfd_sink_destroy_video_decodebin(mm_wfd_sink_t *wfd_sink);
+static int __mm_wfd_sink_destroy_audio_sinkbin(mm_wfd_sink_t *wfd_sink);
+static int __mm_wfd_sink_destroy_video_sinkbin(mm_wfd_sink_t *wfd_sink);
 static int __mm_wfd_sink_destroy_pipeline(mm_wfd_sink_t *wfd_sink);
 static int __mm_wfd_sink_set_pipeline_state(mm_wfd_sink_t *wfd_sink, GstState state, gboolean async);
 
@@ -1146,6 +1154,195 @@ _mm_wfd_sink_reset_basetime(mm_wfd_sink_t *wfd_sink)
 }
 
 int
+__mm_wfd_sink_unprepare_video_pipeline(mm_wfd_sink_t *wfd_sink)
+{
+       GstElement *pipeline  = NULL;
+       GstElement *v_decodebin  = NULL;
+       GstElement *v_sinkbin  = NULL;
+       GstPad *sinkpad = NULL;
+       GstPad *srcpad = NULL;
+       int ret = MM_ERROR_NONE;
+
+       wfd_sink_debug_fenter();
+
+       wfd_sink_return_val_if_fail(wfd_sink &&
+                                                               wfd_sink->pipeline,
+                                                               MM_ERROR_WFD_NOT_INITIALIZED);
+
+       PRINT_WFD_REF_COUNT(wfd_sink);
+       wfd_sink_error("No-error:unprepare video sink bin");
+       if (wfd_sink->pipeline->v_sinkbin && wfd_sink->pipeline->v_sinkbin[WFD_SINK_V_S_BIN].gst) {
+               v_sinkbin = wfd_sink->pipeline->v_sinkbin[WFD_SINK_V_S_BIN].gst;
+
+               if ((pipeline = GST_ELEMENT_CAST(gst_element_get_parent(v_sinkbin)))) {
+                       sinkpad = gst_element_get_static_pad(v_sinkbin, "sink");
+                       if (!sinkpad) {
+                               wfd_sink_error("failed to get sink pad from %s", GST_ELEMENT_NAME(v_sinkbin));
+                               goto ERROR;
+                       }
+
+                       if (gst_pad_is_linked(sinkpad)) {
+                               srcpad = gst_pad_get_peer(sinkpad);
+                               if (!srcpad) {
+                                       wfd_sink_error("failed to get peer pad of %s:%s",
+                                                                       GST_ELEMENT_NAME(GST_PAD_PARENT(sinkpad)), GST_PAD_NAME(sinkpad));
+                                       goto ERROR;
+                               }
+
+                               wfd_sink_debug("try to unlink %s:%s and %s:%s",
+                                                               GST_ELEMENT_NAME(GST_PAD_PARENT(srcpad)), GST_PAD_NAME(srcpad),
+                                                               GST_ELEMENT_NAME(GST_PAD_PARENT(sinkpad)), GST_PAD_NAME(sinkpad));
+                               if (!gst_pad_unlink(srcpad, sinkpad)) {
+                                       wfd_sink_error("failed to unlink %s:%s and %s:%s",
+                                                                       GST_ELEMENT_NAME(GST_PAD_PARENT(srcpad)), GST_PAD_NAME(srcpad),
+                                                                       GST_ELEMENT_NAME(GST_PAD_PARENT(sinkpad)), GST_PAD_NAME(sinkpad));
+                                       goto ERROR;
+                               }
+                               gst_object_unref(srcpad);
+                               srcpad = NULL;
+                       } else {
+                               wfd_sink_debug("video sinkbin's sinkpad is not linked, no need to unlink it");
+                       }
+                       gst_object_unref(sinkpad);
+                       sinkpad = NULL;
+
+                       gst_object_ref(v_sinkbin);
+                       if (!gst_bin_remove(GST_BIN(pipeline), GST_ELEMENT(v_sinkbin))) {
+                               wfd_sink_error("failed to remove %s from %s",
+                                                               GST_ELEMENT_NAME(v_sinkbin), GST_ELEMENT_NAME(pipeline));
+                               goto ERROR;
+                       }
+
+                       gst_object_unref(pipeline);
+                       pipeline = NULL;
+               }
+
+               ret = __mm_wfd_sink_destroy_video_sinkbin(wfd_sink);
+               if (ret != MM_ERROR_NONE) {
+                       wfd_sink_error("failed to destroy video sinkbin");
+                       goto ERROR;
+               }
+       }
+       PRINT_WFD_REF_COUNT(wfd_sink);
+
+       wfd_sink_error("No-error:unprepare video decode bin");
+       if (wfd_sink->pipeline->v_decodebin && wfd_sink->pipeline->v_decodebin[WFD_SINK_V_D_BIN].gst) {
+               v_decodebin = wfd_sink->pipeline->v_decodebin[WFD_SINK_V_D_BIN].gst;
+
+               if ((pipeline = GST_ELEMENT_CAST(gst_element_get_parent(v_decodebin)))) {
+                       sinkpad = gst_element_get_static_pad(v_decodebin, "sink");
+                       if (!sinkpad) {
+                               wfd_sink_error("failed to get sink pad from %s", GST_ELEMENT_NAME(v_decodebin));
+                               goto ERROR;
+                       }
+
+                       if (gst_pad_is_linked(sinkpad)) {
+                               srcpad = gst_pad_get_peer(sinkpad);
+                               if (!srcpad) {
+                                       wfd_sink_error("failed to get peer pad of %s:%s",
+                                                                       GST_ELEMENT_NAME(GST_PAD_PARENT(sinkpad)), GST_PAD_NAME(sinkpad));
+                                       goto ERROR;
+                               }
+
+                               wfd_sink_debug("try to unlink %s:%s and %s:%s",
+                                                               GST_ELEMENT_NAME(GST_PAD_PARENT(srcpad)), GST_PAD_NAME(srcpad),
+                                                               GST_ELEMENT_NAME(GST_PAD_PARENT(sinkpad)), GST_PAD_NAME(sinkpad));
+                               if (!gst_pad_unlink(srcpad, sinkpad)) {
+                                       wfd_sink_error("failed to unlink %s:%s and %s:%s",
+                                                                       GST_ELEMENT_NAME(GST_PAD_PARENT(srcpad)), GST_PAD_NAME(srcpad),
+                                                                       GST_ELEMENT_NAME(GST_PAD_PARENT(sinkpad)), GST_PAD_NAME(sinkpad));
+                                       goto ERROR;
+                               }
+                               gst_object_unref(srcpad);
+                               srcpad = NULL;
+                       } else {
+                               wfd_sink_debug("video decodebin's sinkpad is not linked, no need to unlink it");
+                       }
+                       gst_object_unref(sinkpad);
+                       sinkpad = NULL;
+
+                       srcpad = gst_element_get_static_pad(v_decodebin, "src");
+                       if (!srcpad) {
+                               wfd_sink_error("failed to get src pad from %s", GST_ELEMENT_NAME(v_decodebin));
+                               goto ERROR;
+                       }
+
+                       if (gst_pad_is_linked(srcpad)) {
+                               sinkpad = gst_pad_get_peer(srcpad);
+                               if (!sinkpad) {
+                                       wfd_sink_error("failed to get peer pad of %s:%s",
+                                                                       GST_ELEMENT_NAME(GST_PAD_PARENT(srcpad)), GST_PAD_NAME(srcpad));
+                                       goto ERROR;
+                               }
+
+                               wfd_sink_debug("try to unlink %s:%s and %s:%s",
+                                                               GST_ELEMENT_NAME(GST_PAD_PARENT(srcpad)), GST_PAD_NAME(srcpad),
+                                                               GST_ELEMENT_NAME(GST_PAD_PARENT(sinkpad)), GST_PAD_NAME(sinkpad));
+                               if (!gst_pad_unlink(srcpad, sinkpad)) {
+                                       wfd_sink_error("failed to unlink %s:%s and %s:%s",
+                                                                       GST_ELEMENT_NAME(GST_PAD_PARENT(srcpad)), GST_PAD_NAME(srcpad),
+                                                                       GST_ELEMENT_NAME(GST_PAD_PARENT(sinkpad)), GST_PAD_NAME(sinkpad));
+                                       goto ERROR;
+                               }
+                               gst_object_unref(sinkpad);
+                               sinkpad = NULL;
+                       } else {
+                               wfd_sink_debug("video decodebin's srcpad is not linked, no need to unlink it");
+                       }
+                       gst_object_unref(srcpad);
+                       srcpad = NULL;
+
+                       wfd_sink_error("try to remove %s from %s",
+                                                       GST_ELEMENT_NAME(v_decodebin), GST_ELEMENT_NAME(pipeline));
+                       gst_object_ref(v_decodebin);
+                       if (!gst_bin_remove(GST_BIN(pipeline), GST_ELEMENT(v_decodebin))) {
+                               wfd_sink_error("failed to remove %s from %s",
+                                                               GST_ELEMENT_NAME(v_decodebin), GST_ELEMENT_NAME(pipeline));
+                               goto ERROR;
+                       }
+
+                       gst_object_unref(pipeline);
+                       pipeline = NULL;
+               }
+
+               ret = __mm_wfd_sink_destroy_video_decodebin(wfd_sink);
+               if (ret != MM_ERROR_NONE) {
+                       wfd_sink_error("failed to destroy video decodebin");
+                       goto ERROR;
+               }
+       }
+       PRINT_WFD_REF_COUNT(wfd_sink);
+
+       wfd_sink_debug_fleave();
+
+       return ret;
+
+       /* ERRORS */
+ERROR:
+       if (pipeline) {
+               gst_object_unref(pipeline);
+               pipeline = NULL;
+       }
+
+       if (sinkpad) {
+               gst_object_unref(sinkpad);
+               sinkpad = NULL;
+       }
+
+       if (srcpad) {
+               gst_object_unref(srcpad);
+               srcpad = NULL;
+       }
+
+       /* need to notify to app */
+       MMWFDSINK_POST_MESSAGE(wfd_sink,
+                                                       MM_ERROR_WFD_INTERNAL,
+                                                       MMWFDSINK_CURRENT_STATE(wfd_sink));
+
+       return MM_ERROR_WFD_INTERNAL;
+}
+
+int
 __mm_wfd_sink_prepare_video_pipeline(mm_wfd_sink_t *wfd_sink, GstPad **pad)
 {
        GstElement *v_decodebin  = NULL;
@@ -1226,6 +1423,195 @@ ERROR:
 }
 
 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));
+
+       return MM_ERROR_WFD_INTERNAL;
+}
+
+int
 __mm_wfd_sink_prepare_audio_pipeline(mm_wfd_sink_t *wfd_sink, GstPad **pad)
 {
        GstElement *a_decodebin  = NULL;
@@ -3174,7 +3560,7 @@ static int __mm_wfd_sink_prepare_videosink(mm_wfd_sink_t *wfd_sink, GstElement *
                                        evas_object_geometry_get(obj, &wl_window_x, &wl_window_y, &wl_window_width, &wl_window_height);
 
                                        wfd_sink_debug("x[%d] y[%d] width[%d] height[%d]", wl_window_x, wl_window_y,
-                                               wl_window_width, wl_window_height);
+                                                               wl_window_width, wl_window_height);
 
                                        wl_window = elm_win_wl_window_get(obj);
                                        wl_surface = (struct wl_surface *) ecore_wl_window_surface_get(wl_window);
@@ -3200,10 +3586,10 @@ static int __mm_wfd_sink_prepare_videosink(mm_wfd_sink_t *wfd_sink, GstElement *
 
                                        wfd_sink_debug("set video param : surface_id %d", wl_surface_id);
                                        gst_video_overlay_set_wl_window_wl_surface_id(GST_VIDEO_OVERLAY(video_sink),
-                                               wl_surface_id);
+                                                                                                                               wl_surface_id);
                                        /* After setting window handle, set render rectangle */
                                        gst_video_overlay_set_render_rectangle(GST_VIDEO_OVERLAY(video_sink),
-                                               wl_window_x, wl_window_y, wl_window_width, wl_window_height);
+                                                                                                               wl_window_x, wl_window_y, wl_window_width, wl_window_height);
                                } else {
                                        wfd_sink_debug("display object is NULL!");
                                        return MM_ERROR_WFD_INTERNAL;
@@ -3550,8 +3936,8 @@ int __mm_wfd_sink_create_video_sinkbin(mm_wfd_sink_t *wfd_sink)
        wfd_sink_debug_fenter();
 
        wfd_sink_return_val_if_fail(wfd_sink &&
-                                               wfd_sink->pipeline,
-                                               MM_ERROR_WFD_NOT_INITIALIZED);
+                                                               wfd_sink->pipeline,
+                                                               MM_ERROR_WFD_NOT_INITIALIZED);
 
        if (wfd_sink->pipeline->v_sinkbin != NULL) {
                wfd_sink_error("The video sink bin is already created.");
@@ -3787,9 +4173,9 @@ __mm_wfd_sink_dump_pipeline_state(mm_wfd_sink_t *wfd_sink)
        wfd_sink_debug_fenter();
 
        wfd_sink_return_if_fail(wfd_sink &&
-                                               wfd_sink->pipeline &&
-                                               wfd_sink->pipeline->mainbin &&
-                                               wfd_sink->pipeline->mainbin[WFD_SINK_M_PIPE].gst);
+                                                       wfd_sink->pipeline &&
+                                                       wfd_sink->pipeline->mainbin &&
+                                                       wfd_sink->pipeline->mainbin[WFD_SINK_M_PIPE].gst);
 
        iter = gst_bin_iterate_recurse(GST_BIN(wfd_sink->pipeline->mainbin[WFD_SINK_M_PIPE].gst));
 
@@ -3893,3 +4279,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();
+}