Initial draft of R2 feature 'Secondary Sink' 60/205360/5 accepted/tizen_5.5_unified_mobile_hotfix tizen_5.5_mobile_hotfix tizen_5.5_tv accepted/tizen/5.5/unified/20191031.021926 accepted/tizen/5.5/unified/mobile/hotfix/20201027.084011 accepted/tizen/unified/20190508.111103 submit/tizen/20190507.101459 submit/tizen_5.5/20191031.000004 submit/tizen_5.5_mobile_hotfix/20201026.185103 tizen_5.5.m2_release
authorHyunsoo Park <hance.park@samsung.com>
Thu, 2 May 2019 12:32:06 +0000 (21:32 +0900)
committerHyunsoo Park <hance.park@samsung.com>
Tue, 7 May 2019 10:13:31 +0000 (19:13 +0900)
- add 'mm_wfd_sink_set_coupled_sink_status'
- add process about 'coupling' category in message callback.

*Minor version is updated.

Change-Id: I5753cdd1ba5aef714e0bc0e8cffdf1ba6aa9b93e
Signed-off-by: Hyunsoo Park <hance.park@samsung.com>
packaging/libmm-wfd.spec
src/include/mm_wfd_sink.h
src/include/mm_wfd_sink_priv.h
src/mm_wfd_sink.c
src/mm_wfd_sink_priv.c

index 0262a57..0f0b277 100644 (file)
@@ -1,6 +1,6 @@
 Name:       libmm-wfd
 Summary:    Multimedia Framework Wifi-Display Library
-Version:    0.2.241
+Version:    0.3.0
 Release:    0
 Group:      System/Libraries
 License:    Apache-2.0
index 0026e00..5414e07 100644 (file)
@@ -64,6 +64,13 @@ typedef enum {
        MM_WFD_SINK_VIDEO_CODEC_H264 = 0x1b
 } MMWFDSinkVideoCodec;
 
+typedef enum {
+       MM_WFD_COUPLED_SINK_STATUS_NOT_COUPLED = 0,
+       MM_WFD_COUPLED_SINK_STATUS_COUPLED,
+       MM_WFD_COUPLED_SINK_STATUS_TEARDOWN_COUPLING,
+       MM_WFD_COUPLED_SINK_STATUS_RESERVED
+} MMWFDCoupledSinkStatus;
+
 typedef void(*MMWFDMessageCallback)(int error_type, MMWFDSinkStateType state_type, void *user_data);
 
 /**
@@ -96,6 +103,14 @@ mm_wfd_sink_set_message_callback(g_wfd_sink_handle, msg_callback, (void*)g_wfd_s
 int mm_wfd_sink_create(MMHandleType *wfd_sink);
 
 /**
+ * This function creates a wi-fi display R2 sink object. \n
+ * Description is same to 'mm_wfd_sink_create' but 'wfd_sink' parameter should be handle of wi-fi display R2(primary/secondary) sink. \n
+ *
+ * @param      wfd_sink                [out]   Handle of wi-fi display R2(primary/secondary) sink
+ */
+int mm_wfd_sink_create_r2(MMHandleType *wfd_sink);
+
+/**
  * This function trys to make gstreamer pipeline. \n
  * If wi-fi display sink is realized, the state will become MM_WFD_SINK_STATE_READY.. \n
  *
@@ -481,4 +496,26 @@ int mm_wfd_sink_get_negotiated_audio_bitwidth(MMHandleType wfd_sink_handle,  gin
  */
 int mm_wfd_sink_get_current_state(MMHandleType wfd_sink_handle, gint *state);
 
+/**
+ * This function sets the MAC(or IP) address of coupled wi-fi display R2 sink. \n
+ *
+ * @param   wfd_sink_handle     [in]    Handle of wi-fi display R2 sink
+ * @param   address             [in]   Mac(or IP) address of coupled wi-fi display R2 sink.
+ *
+ * @return  This function returns zero on success, or negative value with error code.
+ *
+ */
+int mm_wfd_sink_set_coupled_sink(MMHandleType wfd_sink_handle, gchar *address);
+
+/**
+ * This function sets the coupling status of wi-fi display R2 sink. \n
+ *
+ * @param   wfd_sink_handle     [in]    Handle of wi-fi display R2 sink
+ * @param   status             [in]   Coupling status of wi-fi display R2 sink.
+ *
+ * @return  This function returns zero on success, or negative value with error code.
+ *
+ */
+int mm_wfd_sink_set_coupled_sink_status(MMHandleType wfd_sink_handle, guint status);
+
 #endif
index 8ae3b20..cafd401 100644 (file)
@@ -249,6 +249,9 @@ typedef struct {
        MMHandleType extend_handle;
        guint msg_callback_id;
 
+       guint coupled_sink_status;
+       gchar *coupled_sink_address;
+       gboolean is_coupled_sink_supported;
 } mm_wfd_sink_t;
 
 
index 0088453..4be7f72 100644 (file)
@@ -54,6 +54,22 @@ int mm_wfd_sink_create(MMHandleType *wfd_sink)
 
 }
 
+int mm_wfd_sink_create_r2(MMHandleType *wfd_sink)
+{
+       int result = MM_ERROR_NONE;
+
+       result = mm_wfd_sink_create(wfd_sink);
+       if (result != MM_ERROR_NONE) {
+               wfd_sink_error("fail to create wi-fi display r2 sink handle. ret[%d]", result);
+               *wfd_sink = (MMHandleType)NULL;
+               return result;
+       }
+
+       ((mm_wfd_sink_t *)*wfd_sink)->is_coupled_sink_supported = TRUE;
+
+       return result;
+}
+
 int mm_wfd_sink_prepare(MMHandleType wfd_sink_handle)
 {
        mm_wfd_sink_t *wfd_sink = (mm_wfd_sink_t *)wfd_sink_handle;
@@ -514,3 +530,65 @@ int mm_wfd_sink_get_current_state(MMHandleType wfd_sink_handle, gint *state)
 
        return result;
 }
+
+int mm_wfd_sink_set_coupled_sink(MMHandleType wfd_sink_handle, gchar* address)
+{
+       mm_wfd_sink_t *wfd_sink = (mm_wfd_sink_t *)wfd_sink_handle;
+       MMWFDSinkStateType cur_state = MM_WFD_SINK_STATE_NONE;
+       int result = MM_ERROR_NONE;
+
+       wfd_sink_debug_fenter();
+
+       wfd_sink_return_val_if_fail(wfd_sink, MM_ERROR_WFD_NOT_INITIALIZED);
+       wfd_sink_return_val_if_fail(address, MM_ERROR_WFD_INVALID_ARGUMENT);
+
+       MMWFDSINK_CMD_LOCK(wfd_sink);
+       cur_state = MMWFDSINK_CURRENT_STATE(wfd_sink);
+       if (cur_state == MM_WFD_SINK_STATE_CONNECTED ||
+               cur_state == MM_WFD_SINK_STATE_PLAYING ||
+               cur_state == MM_WFD_SINK_STATE_PAUSED) {
+               wfd_sink_error("This function must be called before MM_WFD_SINK_STATE_CONNECTED");
+               result = MM_ERROR_WFD_INVALID_STATE;
+       } else {
+               if (wfd_sink->coupled_sink_address) {
+                       wfd_sink_debug("coupled_sink_address is already set. [ %s]", wfd_sink->coupled_sink_address);
+               } else {
+                       wfd_sink->coupled_sink_address = g_strdup(address);
+                       wfd_sink_debug("coupled_sink_address is set [%s]", wfd_sink->coupled_sink_address);
+               }
+       }
+       MMWFDSINK_CMD_UNLOCK(wfd_sink);
+
+       wfd_sink_debug_fleave();
+
+       return result;
+}
+
+int mm_wfd_sink_set_coupled_sink_status(MMHandleType wfd_sink_handle, guint status)
+{
+       mm_wfd_sink_t *wfd_sink = (mm_wfd_sink_t *)wfd_sink_handle;
+       MMWFDSinkStateType cur_state = MM_WFD_SINK_STATE_NONE;
+       int result = MM_ERROR_NONE;
+
+       wfd_sink_debug_fenter();
+
+       wfd_sink_return_val_if_fail(wfd_sink, MM_ERROR_WFD_NOT_INITIALIZED);
+       wfd_sink_return_val_if_fail(status, MM_ERROR_WFD_INVALID_ARGUMENT);
+
+       MMWFDSINK_CMD_LOCK(wfd_sink);
+       cur_state = MMWFDSINK_CURRENT_STATE(wfd_sink);
+       if (cur_state == MM_WFD_SINK_STATE_CONNECTED ||
+               cur_state == MM_WFD_SINK_STATE_PLAYING ||
+               cur_state == MM_WFD_SINK_STATE_PAUSED) {
+               wfd_sink_error("This function must be called before MM_WFD_SINK_STATE_CONNECTED");
+               result = MM_ERROR_WFD_INVALID_STATE;
+       } else {
+               wfd_sink->coupled_sink_status = status;
+               wfd_sink_debug("coupled_sink_status is set [%d]", wfd_sink->coupled_sink_status);
+       }
+       MMWFDSINK_CMD_UNLOCK(wfd_sink);
+
+       wfd_sink_debug_fleave();
+
+       return result;
+}
index c63e5bd..e76bbd8 100644 (file)
@@ -112,6 +112,13 @@ int _mm_wfd_sink_create(mm_wfd_sink_t **wfd_sink, const char *ini_path)
        /* Initialize video resolution */
        new_wfd_sink->supportive_resolution = MM_WFD_SINK_RESOLUTION_UNKNOWN;
 
+       /* Initialize coulped sink information */
+       new_wfd_sink->coupled_sink_address = NULL;
+       new_wfd_sink->coupled_sink_status = MM_WFD_COUPLED_SINK_STATUS_NOT_COUPLED;
+
+       /* In case of R2 sink, it would be TRUE */
+       new_wfd_sink->is_coupled_sink_supported = FALSE;
+
        /* construct attributes */
        new_wfd_sink->attrs = _mmwfd_construct_attribute((MMHandleType)new_wfd_sink);
        if (!new_wfd_sink->attrs) {
@@ -415,6 +422,9 @@ int _mm_wfd_sink_destroy(mm_wfd_sink_t *wfd_sink)
        /* release attributes */
        _mmwfd_deconstruct_attribute(wfd_sink->attrs);
 
+       /* release the others */
+       g_free(wfd_sink->coupled_sink_address);
+
        /* release manager thread  */
        if (MM_ERROR_NONE != _mm_wfd_sink_release_manager(wfd_sink)) {
                wfd_sink_error("failed to release manager");
@@ -950,6 +960,11 @@ _mm_wfd_sink_msg_callback(GstBus *bus, GstMessage *msg, gpointer data)
                                        __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);
+                               } else if (category && !strcmp(category, "coupling")) {
+                                       wfd_sink->coupled_sink_status = MM_WFD_COUPLED_SINK_STATUS_COUPLED;
+                                       wfd_sink->coupled_sink_address = g_strdup(text);
+                                       wfd_sink_debug("coupling info [%d : %s]", wfd_sink->coupled_sink_status, wfd_sink->coupled_sink_address);
+                                       __mm_wfd_sink_set_state(wfd_sink,  MM_WFD_SINK_STATE_DISCONNECTED);
                                }
                                break;
                        case GST_PROGRESS_TYPE_CANCELED:
@@ -979,6 +994,12 @@ _mm_wfd_sink_msg_callback(GstBus *bus, GstMessage *msg, gpointer data)
                                                        MMWFDSINK_POST_MESSAGE(wfd_sink,
                                                        MM_ERROR_WFD_INTERNAL,
                                                        MMWFDSINK_CURRENT_STATE(wfd_sink));
+                               } else if (category && !strcmp(category, "coupling")) {
+                                       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));
                                }
@@ -2721,6 +2742,7 @@ static int __mm_wfd_sink_prepare_source(mm_wfd_sink_t *wfd_sink, GstElement *wfd
        GstStructure *wfd_content_protection = NULL;
        GstStructure *wfd2_video_formats = NULL;
        GstStructure *wfd2_audio_codecs = NULL;
+       GstStructure *wfd_coupled_sink= NULL;
        gint hdcp_version = 0;
        gint hdcp_port = 0;
        guint64 CEA_resolution = 0;
@@ -2793,7 +2815,18 @@ static int __mm_wfd_sink_prepare_source(mm_wfd_sink_t *wfd_sink, GstElement *wfd
                gst_structure_free(wfd_video_formats);
                wfd_video_formats = NULL;
        }
+       /* set coupled sink information for Wi-Fi Display session negotiation */
+       wfd_coupled_sink = gst_structure_new("wfd_coupled_sink",
+                                                                                       "coupled_sink_status", G_TYPE_INT, wfd_sink->coupled_sink_status,
+                                                                                       "coupled_sink_address", G_TYPE_STRING, wfd_sink->coupled_sink_address,
+                                                                                       "is_coupled_sink_supported", G_TYPE_BOOLEAN, wfd_sink->is_coupled_sink_supported,
+                                                                                       NULL);
 
+       if (wfd_coupled_sink) {
+               g_object_set(G_OBJECT(wfdsrc), "wfd-coupled-sink", wfd_coupled_sink, NULL);
+               gst_structure_free(wfd_coupled_sink);
+               wfd_coupled_sink = NULL;
+       }
 
        /* set hdcp parameter for Wi-Fi Display session negotiation */
        if (wfd_sink->ini.wfd_content_protection.enable_hdcp) {