From: Sangchul Lee Date: Fri, 23 Apr 2021 04:09:16 +0000 (+0900) Subject: Add API set for the ICE connection state X-Git-Tag: submit/tizen/20210729.023123~77 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=6f25c59892575c1411926d0866d95ccdc9bec4f5;p=platform%2Fcore%2Fapi%2Fwebrtc.git Add API set for the ICE connection state These correspond to the 'iceConnectionState' and 'oniceconnectionstatechange' property of the RTCPeerConnection respectively. Enums are added as below. - WEBRTC_ICE_CONNECTION_STATE_NEW - WEBRTC_ICE_CONNECTION_STATE_CHECKING - WEBRTC_ICE_CONNECTION_STATE_CONNECTED - WEBRTC_ICE_CONNECTION_STATE_COMPLETED - WEBRTC_ICE_CONNECTION_STATE_FAILED - WEBRTC_ICE_CONNECTION_STATE_DISCONNECTED - WEBRTC_ICE_CONNECTION_STATE_CLOSED Functions are added as below. - webrtc_set[unset]_ice_connection_state_change_cb() - webrtc_get_ice_connection_state() [Version] 0.1.164 [Issue Type] API Change-Id: If11019e7d57667d031c676e12c8c688fcc03da30 Signed-off-by: Sangchul Lee --- diff --git a/include/webrtc.h b/include/webrtc.h index 1e5b1811..5621930c 100644 --- a/include/webrtc.h +++ b/include/webrtc.h @@ -129,6 +129,20 @@ typedef enum { WEBRTC_ICE_GATHERING_STATE_COMPLETE, /**< Complete */ } webrtc_ice_gathering_state_e; +/** + * @brief Enumeration for WebRTC ICE connection state. + * @since_tizen 6.5 + */ +typedef enum { + WEBRTC_ICE_CONNECTION_STATE_NEW, /**< New */ + WEBRTC_ICE_CONNECTION_STATE_CHECKING, /**< Checking */ + WEBRTC_ICE_CONNECTION_STATE_CONNECTED, /**< Connected */ + WEBRTC_ICE_CONNECTION_STATE_COMPLETED, /**< Completed */ + WEBRTC_ICE_CONNECTION_STATE_FAILED, /**< Failed */ + WEBRTC_ICE_CONNECTION_STATE_DISCONNECTED, /**< Disconnected */ + WEBRTC_ICE_CONNECTION_STATE_CLOSED, /**< Closed */ +} webrtc_ice_connection_state_e; + /** * @brief Enumeration for WebRTC media source type. * @since_tizen 6.5 @@ -258,6 +272,18 @@ typedef void (*webrtc_signaling_state_change_cb)(webrtc_h webrtc, webrtc_signali */ typedef void (*webrtc_ice_gathering_state_change_cb)(webrtc_h webrtc, webrtc_ice_gathering_state_e state, void *user_data); +/** + * @brief Called when the WebRTC ICE connection state is changed. + * @since_tizen 6.5 + * @remarks The @a webrtc is the same object for which the callback was set.\nThe @a webrtc should not be released. + * @param[in] webrtc WebRTC handle + * @param[in] state The ICE connection state + * @param[in] user_data The user data passed from the callback registration function + * @see webrtc_set_ice_connection_state_change_cb() + * @see webrtc_unset_ice_connection_state_change_cb() + */ +typedef void (*webrtc_ice_connection_state_change_cb)(webrtc_h webrtc, webrtc_ice_connection_state_e state, void *user_data); + /** * @brief Called when the buffer state of media packet source is changed. * @since_tizen 6.5 @@ -969,6 +995,52 @@ int webrtc_unset_ice_gathering_state_change_cb(webrtc_h webrtc); */ int webrtc_get_ice_gathering_state(webrtc_h webrtc, webrtc_ice_gathering_state_e *state); +/** + * @brief Sets a callback function to be invoked when the WebRTC ICE connection state is changed. + * @since_tizen 6.5 + * @param[in] webrtc WebRTC handle + * @param[in] callback Callback function pointer + * @param[in] user_data The user data to be passed to the callback function + * @return @c 0 on success, + * otherwise a negative error value + * @retval #WEBRTC_ERROR_NONE Successful + * @retval #WEBRTC_ERROR_INVALID_PARAMETER Invalid parameter + * @post webrtc_ice_connection_state_change_cb() will be invoked. + * @see webrtc_unset_ice_connection_state_change_cb() + * @see webrtc_ice_connection_state_change_cb() + * @see webrtc_get_ice_connection_state() + */ +int webrtc_set_ice_connection_state_change_cb(webrtc_h webrtc, webrtc_ice_connection_state_change_cb callback, void *user_data); + +/** + * @brief Unsets the ICE connection state change callback function. + * @since_tizen 6.5 + * @param[in] webrtc WebRTC handle + * @return @c 0 on success, + * otherwise a negative error value + * @retval #WEBRTC_ERROR_NONE Successful + * @retval #WEBRTC_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #WEBRTC_ERROR_INVALID_OPERATION Invalid operation + * @see webrtc_set_ice_connection_state_change_cb() + * @see webrtc_get_ice_connection_state() + */ +int webrtc_unset_ice_connection_state_change_cb(webrtc_h webrtc); + +/** + * @brief Gets the ICE connection state. + * @since_tizen 6.5 + * @remarks The default value is #WEBRTC_ICE_CONNECTION_STATE_NEW. + * @param[in] webrtc WebRTC handle + * @param[out] state The ICE connection state + * @return @c 0 on success, + * otherwise a negative error value + * @retval #WEBRTC_ERROR_NONE Successful + * @retval #WEBRTC_ERROR_INVALID_PARAMETER Invalid parameter + * @see webrtc_set_ice_connection_state_change_cb() + * @see webrtc_unset_ice_connection_state_change_cb() + */ +int webrtc_get_ice_connection_state(webrtc_h webrtc, webrtc_ice_connection_state_e *state); + /** * @brief Sets a negotiation needed callback function to be invoked when a change has occurred which requires session negotiation. * @since_tizen 6.5 diff --git a/include/webrtc_private.h b/include/webrtc_private.h index a56d95f7..8d48ef28 100644 --- a/include/webrtc_private.h +++ b/include/webrtc_private.h @@ -358,6 +358,8 @@ typedef struct _webrtc_s { webrtc_callbacks_s peer_connection_state_change_cb; webrtc_callbacks_s signaling_state_change_cb; webrtc_callbacks_s ice_gathering_state_change_cb; + webrtc_callbacks_s ice_connection_state_change_cb; + webrtc_callbacks_s negotiation_needed_cb; webrtc_callbacks_s ice_candidate_cb; webrtc_callbacks_s track_added_cb; @@ -369,8 +371,8 @@ typedef struct _webrtc_s { webrtc_peer_connection_state_e peer_connection_state; webrtc_signaling_state_e signaling_state; webrtc_ice_gathering_state_e ice_gathering_state; - const gchar *ice_connection_state; - } internal_states; + webrtc_ice_connection_state_e ice_connection_state; + } negotiation_states; #ifdef TIZEN_FEATURE_RES_MGR webrtc_resource_s resource; #endif diff --git a/packaging/capi-media-webrtc.spec b/packaging/capi-media-webrtc.spec index 97e08213..bd22eb32 100644 --- a/packaging/capi-media-webrtc.spec +++ b/packaging/capi-media-webrtc.spec @@ -1,6 +1,6 @@ Name: capi-media-webrtc Summary: A WebRTC library in Tizen Native API -Version: 0.1.163 +Version: 0.1.164 Release: 0 Group: Multimedia/API License: Apache-2.0 diff --git a/src/webrtc.c b/src/webrtc.c index 102756c4..fd192429 100644 --- a/src/webrtc.c +++ b/src/webrtc.c @@ -647,7 +647,7 @@ int webrtc_get_peer_connection_state(webrtc_h webrtc, webrtc_peer_connection_sta g_mutex_lock(&_webrtc->mutex); - *state = _webrtc->internal_states.peer_connection_state; + *state = _webrtc->negotiation_states.peer_connection_state; LOG_INFO("state[%d]", *state); @@ -710,7 +710,7 @@ int webrtc_get_signaling_state(webrtc_h webrtc, webrtc_signaling_state_e *state) g_mutex_lock(&_webrtc->mutex); - *state = _webrtc->internal_states.signaling_state; + *state = _webrtc->negotiation_states.signaling_state; LOG_INFO("state[%d]", *state); @@ -773,7 +773,70 @@ int webrtc_get_ice_gathering_state(webrtc_h webrtc, webrtc_ice_gathering_state_e g_mutex_lock(&_webrtc->mutex); - *state = _webrtc->internal_states.ice_gathering_state; + *state = _webrtc->negotiation_states.ice_gathering_state; + + LOG_INFO("state[%d]", *state); + + g_mutex_unlock(&_webrtc->mutex); + + return WEBRTC_ERROR_NONE; +} + +int webrtc_set_ice_connection_state_change_cb(webrtc_h webrtc, webrtc_ice_connection_state_change_cb callback, void *user_data) +{ + webrtc_s *_webrtc = (webrtc_s*)webrtc; + + RET_VAL_IF(_webrtc == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "webrtc is NULL"); + RET_VAL_IF(callback == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "callback is NULL"); + + g_mutex_lock(&_webrtc->mutex); + + RET_VAL_WITH_UNLOCK_IF(_webrtc->state != WEBRTC_STATE_IDLE, WEBRTC_ERROR_INVALID_STATE, &_webrtc->mutex, "the state should be IDLE"); + + LOG_WARNING_IF_CALLBACK_EXISTS(_webrtc->ice_connection_state_change_cb); + + _webrtc->ice_connection_state_change_cb.callback = callback; + _webrtc->ice_connection_state_change_cb.user_data = user_data; + + LOG_INFO("callback[%p] user_data[%p]", callback, user_data); + + g_mutex_unlock(&_webrtc->mutex); + + return WEBRTC_ERROR_NONE; +} + +int webrtc_unset_ice_connection_state_change_cb(webrtc_h webrtc) +{ + webrtc_s *_webrtc = (webrtc_s*)webrtc; + + RET_VAL_IF(_webrtc == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "webrtc is NULL"); + + g_mutex_lock(&_webrtc->mutex); + + RET_VAL_WITH_UNLOCK_IF(_webrtc->state != WEBRTC_STATE_IDLE, WEBRTC_ERROR_INVALID_STATE, &_webrtc->mutex, "the state should be IDLE"); + RET_VAL_WITH_UNLOCK_IF(_webrtc->ice_connection_state_change_cb.callback == NULL, WEBRTC_ERROR_INVALID_OPERATION, &_webrtc->mutex, "callback was not set"); + + LOG_INFO("callback[%p] user_data[%p] is reset to NULL", + _webrtc->ice_connection_state_change_cb.callback, _webrtc->ice_connection_state_change_cb.user_data); + + _webrtc->ice_connection_state_change_cb.callback = NULL; + _webrtc->ice_connection_state_change_cb.user_data = NULL; + + g_mutex_unlock(&_webrtc->mutex); + + return WEBRTC_ERROR_NONE; +} + +int webrtc_get_ice_connection_state(webrtc_h webrtc, webrtc_ice_connection_state_e *state) +{ + webrtc_s *_webrtc = (webrtc_s*)webrtc; + + RET_VAL_IF(_webrtc == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "webrtc is NULL"); + RET_VAL_IF(state == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "state is NULL"); + + g_mutex_lock(&_webrtc->mutex); + + *state = _webrtc->negotiation_states.ice_connection_state; LOG_INFO("state[%d]", *state); diff --git a/src/webrtc_private.c b/src/webrtc_private.c index 2439a695..6f940a3e 100644 --- a/src/webrtc_private.c +++ b/src/webrtc_private.c @@ -46,6 +46,11 @@ typedef struct { webrtc_ice_gathering_state_e state; } ice_gathering_state_info_s; +typedef struct { + const char *str; + webrtc_ice_connection_state_e state; +} ice_connection_state_info_s; + static direction_info_s __direction_info[] = { [WEBRTC_TRANSCEIVER_DIRECTION_SENDONLY] = { "SENDONLY", GST_WEBRTC_RTP_TRANSCEIVER_DIRECTION_SENDONLY }, [WEBRTC_TRANSCEIVER_DIRECTION_RECVONLY] = { "RECVONLY", GST_WEBRTC_RTP_TRANSCEIVER_DIRECTION_RECVONLY }, @@ -76,6 +81,16 @@ static ice_gathering_state_info_s __ice_gathering_state_info[] = { [GST_WEBRTC_ICE_GATHERING_STATE_COMPLETE] = { "COMPLETE", WEBRTC_ICE_GATHERING_STATE_COMPLETE }, }; +static ice_connection_state_info_s __ice_connection_state_info[] = { + [GST_WEBRTC_ICE_CONNECTION_STATE_NEW] = { "NEW", WEBRTC_ICE_CONNECTION_STATE_NEW }, + [GST_WEBRTC_ICE_CONNECTION_STATE_CHECKING] = { "CHECKING", WEBRTC_ICE_CONNECTION_STATE_CHECKING }, + [GST_WEBRTC_ICE_CONNECTION_STATE_CONNECTED] = { "CONNECTED", WEBRTC_ICE_CONNECTION_STATE_CONNECTED }, + [GST_WEBRTC_ICE_CONNECTION_STATE_COMPLETED] = { "COMPLETED", WEBRTC_ICE_CONNECTION_STATE_COMPLETED }, + [GST_WEBRTC_ICE_CONNECTION_STATE_FAILED] = { "FAILED", WEBRTC_ICE_CONNECTION_STATE_FAILED }, + [GST_WEBRTC_ICE_CONNECTION_STATE_DISCONNECTED] = { "DISCONNECTED", WEBRTC_ICE_CONNECTION_STATE_DISCONNECTED }, + [GST_WEBRTC_ICE_CONNECTION_STATE_CLOSED] = { "CLOSED", WEBRTC_ICE_CONNECTION_STATE_CLOSED }, +}; + static const char *__get_error_string(webrtc_error_e error) { switch (error) { @@ -292,6 +307,23 @@ static void __invoke_ice_gathering_state_change_cb(webrtc_s *webrtc, GstWebRTCIC GENERATE_DOT(webrtc, "ICE_GATHERING_STATE_%s", __ice_gathering_state_info[state].str); } +static void __invoke_ice_connection_state_change_cb(webrtc_s *webrtc, GstWebRTCICEConnectionState state) +{ + webrtc_callbacks_s *cb; + + RET_IF(webrtc == NULL, "webrtc is NULL"); + + cb = &webrtc->ice_connection_state_change_cb; + + if (cb->callback) { + LOG_DEBUG(">>> callback[%p], user_data[%p]", cb->callback, cb->user_data); + ((webrtc_ice_connection_state_change_cb)(cb->callback))((webrtc_h)webrtc, __ice_connection_state_info[state].state, cb->user_data); + LOG_DEBUG("<<< end of the callback"); + } + + GENERATE_DOT(webrtc, "ICE_CONNECTION_STATE_%s", __ice_connection_state_info[state].str); +} + static gboolean __bus_watch_cb(GstBus *bus, GstMessage *message, gpointer user_data) { webrtc_s *webrtc = (webrtc_s *)user_data; @@ -697,7 +729,7 @@ static void __webrtcbin_peer_connection_state_cb(GstElement *webrtcbin, GParamSp g_object_get(webrtcbin, "connection-state", &state, NULL); LOG_DEBUG("[PeerConnectionState] is changed to [%s]", __peer_connection_state_info[state].str); - webrtc->internal_states.peer_connection_state = __peer_connection_state_info[state].state; + webrtc->negotiation_states.peer_connection_state = __peer_connection_state_info[state].state; __invoke_peer_connection_state_change_cb(webrtc, state); @@ -729,7 +761,7 @@ static void __webrtcbin_signaling_state_cb(GstElement *webrtcbin, GParamSpec * p g_object_get(webrtcbin, "signaling-state", &state, NULL); LOG_DEBUG("[SignalingState] is changed to [%s]", __signaling_state_info[state].str); - webrtc->internal_states.signaling_state = __signaling_state_info[state].state; + webrtc->negotiation_states.signaling_state = __signaling_state_info[state].state; __invoke_signaling_state_change_cb(webrtc, state); } @@ -745,57 +777,28 @@ static void __webrtcbin_ice_gathering_state_cb(GstElement *webrtcbin, GParamSpec g_object_get(webrtcbin, "ice-gathering-state", &state, NULL); LOG_DEBUG("[IceGatheringState] is changed to [%s]", __ice_gathering_state_info[state].str); - webrtc->internal_states.ice_gathering_state = __ice_gathering_state_info[state].state; + webrtc->negotiation_states.ice_gathering_state = __ice_gathering_state_info[state].state; __invoke_ice_gathering_state_change_cb(webrtc, state); } -static void __webrtcbin_ice_connection_state_cb(GstElement *webrtcbin, GParamSpec * pspec, gpointer user_data) +static void __webrtcbin_ice_connection_state_cb(GstElement *webrtcbin, GParamSpec *pspec, gpointer user_data) { webrtc_s *webrtc = (webrtc_s *)user_data; - GstWebRTCICEConnectionState ice_connection_state; - const gchar *new_state = "UNKNOWN"; + GstWebRTCICEConnectionState state; RET_IF(webrtcbin == NULL, "webrtcbin is NULL"); RET_IF(webrtc == NULL, "webrtc is NULL"); - g_object_get(webrtcbin, "ice-connection-state", &ice_connection_state, NULL); - - switch (ice_connection_state) { - case GST_WEBRTC_ICE_CONNECTION_STATE_NEW: - new_state = "NEW"; - break; - - case GST_WEBRTC_ICE_CONNECTION_STATE_CHECKING: - new_state = "CHECKING"; - break; - - case GST_WEBRTC_ICE_CONNECTION_STATE_CONNECTED: - new_state = "CONNECTED"; - break; + g_object_get(webrtcbin, "ice-connection-state", &state, NULL); - case GST_WEBRTC_ICE_CONNECTION_STATE_COMPLETED: - new_state = "COMPLETED"; - break; + LOG_DEBUG("[IceConnectionState] is changed to [%s]", __ice_connection_state_info[state].str); + webrtc->negotiation_states.ice_connection_state = __ice_connection_state_info[state].state; - case GST_WEBRTC_ICE_CONNECTION_STATE_FAILED: - new_state = "FAILED"; + __invoke_ice_connection_state_change_cb(webrtc, state); + if (state == GST_WEBRTC_ICE_CONNECTION_STATE_FAILED) __invoke_error_cb(webrtc, WEBRTC_ERROR_CONNECTION_FAILED); - break; - - case GST_WEBRTC_ICE_CONNECTION_STATE_DISCONNECTED: - new_state = "DISCONNECTED"; - break; - - case GST_WEBRTC_ICE_CONNECTION_STATE_CLOSED: - new_state = "CLOSED"; - break; - } - - LOG_DEBUG("[IceConnectionState] is changed to [%s]", new_state); - - webrtc->internal_states.ice_connection_state = new_state; } static GstPad* __add_no_target_ghostpad(GstBin *bin, const char *pad_name, bool is_src)