Change function parameter and add some member variable 59/83059/3 accepted/tizen/common/20160811.145640 accepted/tizen/ivi/20160812.010625 accepted/tizen/mobile/20160812.010647 accepted/tizen/tv/20160812.010602 submit/tizen/20160810.075454 submit/tizen/20160811.023523
authorSeokHoon Lee <andy.shlee@samsung.com>
Tue, 9 Aug 2016 04:14:52 +0000 (13:14 +0900)
committerSeokHoon Lee <andy.shlee@samsung.com>
Tue, 9 Aug 2016 05:25:10 +0000 (14:25 +0900)
 - mm_wfd_sink_prepare_video_pipeline function parameter change.
 - mm_wfd_sink_prepare_audio_pipeline function parameter change.
 - add extend_handle/msg_callback_id/update_stream_info_sig_id/chage_av_format_sig_id
 - remove static in some function

Signed-off-by: SeokHoon Lee <andy.shlee@samsung.com>
Change-Id: I86365f90f5a11408b85367d4eaa2ce22fe8bdcad

packaging/libmm-wfd.spec
src/include/mm_wfd_sink_priv.h
src/mm_wfd_sink_manager.c [changed mode: 0755->0644]
src/mm_wfd_sink_priv.c

index eb054b0a10158bc321c815eeee0e31bac6569c53..68b15aa157a37cf3cfaee43f7023bba32c2b18fb 100644 (file)
@@ -1,6 +1,6 @@
 Name:       libmm-wfd
 Summary:    Multimedia Framework Wifi-Display Library
-Version:    0.2.201
+Version:    0.2.202
 Release:    0
 Group:      System/Libraries
 License:    Apache-2.0
index 5830683ab65263278cf986db716d5b100896db30..97fb4cc29f4c8981a11eb013e17f1ec8b20b1247 100644 (file)
@@ -159,11 +159,11 @@ typedef struct {
 } MMWFDSinkGstElement;
 
 typedef struct {
-       MMWFDSinkGstElement     *mainbin;
-       MMWFDSinkGstElement     *a_decodebin;
-       MMWFDSinkGstElement     *v_decodebin;
-       MMWFDSinkGstElement     *a_sinkbin;
-       MMWFDSinkGstElement     *v_sinkbin;
+       MMWFDSinkGstElement     *mainbin;
+       MMWFDSinkGstElement     *a_decodebin;
+       MMWFDSinkGstElement     *v_decodebin;
+       MMWFDSinkGstElement     *a_sinkbin;
+       MMWFDSinkGstElement     *v_sinkbin;
 } MMWFDSinkGstPipelineInfo;
 
 typedef struct {
@@ -183,13 +183,15 @@ typedef struct {
        int(*unprepare)(MMHandleType wfd_sink);
 } MMWFDSinkPrivateFunc;
 
-#define MMWFDSINK_GET_ATTRS(x_wfd) ((x_wfd)? ((mm_wfd_sink_t*)x_wfd)->attrs : (MMHandleType)NULL)
+#define MMWFDSINK_GET_ATTRS(x_wfd) ((x_wfd) ? ((mm_wfd_sink_t*)x_wfd)->attrs : (MMHandleType)NULL)
 
 typedef struct {
        /* gstreamer pipeline */
        MMWFDSinkGstPipelineInfo *pipeline;
        gboolean audio_decodebin_is_linked;
        gboolean video_decodebin_is_linked;
+       gulong update_stream_info_sig_id;
+       gulong change_av_format_sig_id;
 
        /* timestamp compensation */
        gboolean need_to_reset_basetime;
@@ -234,6 +236,9 @@ typedef struct {
        gboolean manager_thread_exit;
 
        MMWFDSinkPrivateFunc *func_table;
+       MMHandleType extend_handle;
+       guint msg_callback_id;
+
 } mm_wfd_sink_t;
 
 
@@ -251,10 +256,13 @@ int _mm_wfd_sink_set_resolution(mm_wfd_sink_t *wfd_sink, MMWFDSinkResolution res
 
 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);
-int __mm_wfd_sink_prepare_audio_pipeline(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);
 
 const gchar *_mm_wfds_sink_get_state_name(MMWFDSinkStateType state);
-
+int __mm_wfd_sink_check_state(mm_wfd_sink_t *wfd_sink, MMWFDSinkCommandType cmd);
+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);
 #endif
-
old mode 100755 (executable)
new mode 100644 (file)
index 566d0d4..b4f9114
@@ -127,14 +127,14 @@ __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)) {
+                                       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)) {
+                                       if (MM_ERROR_NONE != __mm_wfd_sink_prepare_video_pipeline(wfd_sink, NULL)) {
                                        wfd_sink_error("failed to prepare video pipeline.....");
                                        goto EXIT;
                                }
index b990df82c75ecc300176eca3ad4e22a8ea54a284..34f77ffe5f147edec93166ec4fd5762e57c3546c 100644 (file)
 /* 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_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);
 
 /* 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 */
@@ -532,6 +527,9 @@ _mm_wfd_bus_sync_callback(GstBus *bus, GstMessage *message, gpointer data)
                                                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;
@@ -571,235 +569,236 @@ _mm_wfd_sink_msg_callback(GstBus *bus, GstMessage *msg, gpointer data)
                                        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;
+       case GST_MESSAGE_ERROR: {
+                       GError *error = NULL;
+                       gchar *debug = NULL;
 
-                               /* get error code */
-                               gst_message_parse_error(msg, &error, &debug);
+                       /* get error code */
+                       gst_message_parse_error(msg, &error, &debug);
 
-                               wfd_sink_error("error : %s", error->message);
-                               wfd_sink_error("debug : %s", debug);
+                       wfd_sink_error("error : %s", error->message);
+                       wfd_sink_error("debug : %s", debug);
 
-                               MMWFDSINK_FREEIF(debug);
-                               g_error_free(error);
-                       }
-                       break;
+                       MMWFDSINK_FREEIF(debug);
+                       g_error_free(error);
+               }
+               break;
 
-               case GST_MESSAGE_WARNING: {
-                               char *debug = NULL;
-                               GError *error = NULL;
+       case GST_MESSAGE_WARNING: {
+                       char *debug = NULL;
+                       GError *error = NULL;
 
-                               gst_message_parse_warning(msg, &error, &debug);
+                       gst_message_parse_warning(msg, &error, &debug);
 
-                               wfd_sink_error("warning : %s", error->message);
-                               wfd_sink_error("debug : %s", debug);
+                       wfd_sink_error("warning : %s", error->message);
+                       wfd_sink_error("debug : %s", debug);
 
-                               MMWFDSINK_FREEIF(debug);
-                               g_error_free(error);
-                       }
-                       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;
-
-                               /* 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;
-                               }
+       case GST_MESSAGE_STATE_CHANGED: {
+                       const GValue *voldstate, *vnewstate, *vpending;
+                       GstState oldstate, newstate, pending;
+                       const GstStructure *structure;
 
-                               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;
-                               }
+                       /* 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;
                        }
-                       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",
-                                                               (GST_STR_NULL(GST_OBJECT_NAME(clock))));
-                               }
+       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;
 
-                               wfd_sink->clock = clock;
+                       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))));
                        }
-                       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, "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));
                                }
                        }
-                       break;
+               }
+               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_wfd_sink_disconnect (wfd_sink); */
-                                               MMWFDSINK_POST_MESSAGE(wfd_sink,
+       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 {
-                                               wfd_sink_error("got error : %s", GST_STR_NULL(text));
-                                       }
-                                       break;
-                               default:
-                                       wfd_sink_error("progress message has no type");
-                                       return ret;
+                               } 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_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));
                                }
-
-                               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;
@@ -884,7 +883,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;
@@ -1147,9 +1146,10 @@ _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_prepare_video_pipeline(mm_wfd_sink_t *wfd_sink, GstPad **pad)
 {
-       GstElement *bin = NULL;
+       GstElement *v_decodebin  = NULL;
+       GstElement *v_sinkbin  = NULL;
 
        wfd_sink_debug_fenter();
 
@@ -1185,9 +1185,10 @@ __mm_wfd_sink_prepare_video_pipeline(mm_wfd_sink_t *wfd_sink)
 
        /* set video decodebin state as READY */
        if (wfd_sink->pipeline->v_decodebin && wfd_sink->pipeline->v_decodebin[WFD_SINK_V_D_BIN].gst) {
-               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)) {
+               v_decodebin = wfd_sink->pipeline->v_decodebin[WFD_SINK_V_D_BIN].gst;
+               if (GST_STATE(v_decodebin) <= GST_STATE_NULL) {
+                       wfd_sink_debug("need to prepare %s", GST_ELEMENT_NAME(v_decodebin));
+                       if (GST_STATE_CHANGE_FAILURE == gst_element_set_state(v_decodebin, GST_STATE_READY)) {
                                wfd_sink_error("failed to set state(READY) to video decodebin");
                                goto ERROR;
                        }
@@ -1198,9 +1199,10 @@ __mm_wfd_sink_prepare_video_pipeline(mm_wfd_sink_t *wfd_sink)
 
        /* set video sinkbin state as READY */
        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)) {
+               v_sinkbin = wfd_sink->pipeline->v_sinkbin[WFD_SINK_V_S_BIN].gst;
+               if (GST_STATE(v_sinkbin) <= GST_STATE_NULL) {
+                       wfd_sink_debug("need to prepare %s", GST_ELEMENT_NAME(v_sinkbin));
+                       if (GST_STATE_CHANGE_FAILURE == gst_element_set_state(v_sinkbin, GST_STATE_READY)) {
                                wfd_sink_error("failed to set state(READY) to video sinkbin");
                                goto ERROR;
                        }
@@ -1223,9 +1225,11 @@ ERROR:
        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 *a_decodebin  = NULL;
+       GstElement *a_sinkbin  = NULL;
 
        wfd_sink_debug_fenter();
 
@@ -1259,9 +1263,10 @@ int __mm_wfd_sink_prepare_audio_pipeline(mm_wfd_sink_t *wfd_sink)
 
        /* set audio decodebin state as READY */
        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)) {
+               a_decodebin = wfd_sink->pipeline->a_decodebin[WFD_SINK_A_D_BIN].gst;
+               if (GST_STATE(a_decodebin) <= GST_STATE_NULL) {
+                       wfd_sink_debug("need to prepare %s", GST_ELEMENT_NAME(a_decodebin));
+                       if (GST_STATE_CHANGE_FAILURE == gst_element_set_state(a_decodebin, GST_STATE_READY)) {
                                wfd_sink_error("failed to set state(READY) to audio decodebin");
                                goto ERROR;
                        }
@@ -1272,9 +1277,10 @@ int __mm_wfd_sink_prepare_audio_pipeline(mm_wfd_sink_t *wfd_sink)
 
        /* set audio sinkbin state as READY */
        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)) {
+               a_sinkbin = wfd_sink->pipeline->a_sinkbin[WFD_SINK_A_S_BIN].gst;
+               if (GST_STATE(a_sinkbin) <= GST_STATE_NULL) {
+                       wfd_sink_debug("need to prepare %s", GST_ELEMENT_NAME(a_sinkbin));
+                       if (GST_STATE_CHANGE_FAILURE == gst_element_set_state(a_sinkbin , GST_STATE_READY)) {
                                wfd_sink_error("failed to set state(READY) to audio sinkbin");
                                goto ERROR;
                        }
@@ -1560,7 +1566,7 @@ __mm_wfd_sink_demux_pad_added(GstElement *ele, GstPad *pad, gpointer data)
                                        (gpointer)wfd_sink,
                                        NULL);
 
-               if (MM_ERROR_NONE != __mm_wfd_sink_prepare_video_pipeline(wfd_sink)) {
+               if (MM_ERROR_NONE != __mm_wfd_sink_prepare_video_pipeline(wfd_sink, &sinkpad)) {
                        wfd_sink_error("failed to prepare video pipeline....");
                        goto ERROR;
                }
@@ -1580,7 +1586,7 @@ __mm_wfd_sink_demux_pad_added(GstElement *ele, GstPad *pad, gpointer data)
                                        (gpointer)wfd_sink,
                                        NULL);
 
-               if (MM_ERROR_NONE != __mm_wfd_sink_prepare_audio_pipeline(wfd_sink)) {
+               if (MM_ERROR_NONE != __mm_wfd_sink_prepare_audio_pipeline(wfd_sink, &sinkpad)) {
                        wfd_sink_error("failed to prepare audio pipeline....");
                        goto ERROR;
                }
@@ -1952,9 +1958,11 @@ static int __mm_wfd_sink_prepare_source(mm_wfd_sink_t *wfd_sink, GstElement *wfd
                        g_object_set(G_OBJECT(wfdsrc), "wfd-content-protection", wfd_content_protection, 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();
 
@@ -2091,7 +2099,7 @@ 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);
@@ -2433,7 +2441,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;
@@ -2447,6 +2455,11 @@ static int __mm_wfd_sink_create_audio_decodebin(mm_wfd_sink_t *wfd_sink)
                                                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:
@@ -2657,7 +2670,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;
@@ -2673,6 +2686,11 @@ static int __mm_wfd_sink_create_audio_sinkbin(mm_wfd_sink_t *wfd_sink)
                                                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);
        if (!a_sinkbin) {
@@ -3203,7 +3221,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;
@@ -3410,7 +3428,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;
@@ -3426,6 +3444,11 @@ static int __mm_wfd_sink_create_video_sinkbin(mm_wfd_sink_t *wfd_sink)
                                                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);
        if (!v_sinkbin) {
@@ -3592,6 +3615,8 @@ static int __mm_wfd_sink_destroy_pipeline(mm_wfd_sink_t *wfd_sink)
                        if (ret != GST_STATE_CHANGE_SUCCESS) {
                                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");
                        }
 
                        if (MM_ERROR_NONE != __mm_wfd_sink_destroy_video_decodebin(wfd_sink)) {
@@ -3623,6 +3648,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;