From: Sangchul Lee Date: Thu, 29 Feb 2024 02:40:47 +0000 (+0900) Subject: webrtc_internal: Add webrtc_start_sync() function X-Git-Tag: accepted/tizen/8.0/unified/20240308.173324~5 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=ef0c8ad1e94441a702d67dc1671191b6f7e9fc8a;p=platform%2Fcore%2Fapi%2Fwebrtc.git webrtc_internal: Add webrtc_start_sync() function The main difference with webrtc_start() is that this returns after changing state to WEBRTC_STATE_NEGOTIATING without invoking state changed callback. [Version] 0.4.46 [Issue Type] Internal API Change-Id: Ia4d295de5ec861a7b7d20deed35c6c764a0e01d7 Signed-off-by: Sangchul Lee --- diff --git a/include/webrtc_internal.h b/include/webrtc_internal.h index c3d7755c..8c72075f 100644 --- a/include/webrtc_internal.h +++ b/include/webrtc_internal.h @@ -489,6 +489,29 @@ int webrtc_set_rtp_packet_drop_probability(webrtc_h webrtc, bool sender, float p */ int webrtc_get_rtp_packet_drop_probability(webrtc_h webrtc, bool sender, float *probability); +/** + * @internal + * @brief Starts the WebRTC synchronously. + * @since_tizen 8.0 + * @remarks The main difference with webrtc_start() is that this returns after changing state to #WEBRTC_STATE_NEGOTIATING.\n + * webrtc_state_changed_cb() will not be invoked. + * @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 + * @retval #WEBRTC_ERROR_INVALID_STATE Invalid state + * @retval #WEBRTC_ERROR_RESOURCE_FAILED Resource failed + * @pre webrtc_ice_candidate_cb() must be set by calling webrtc_set_ice_candidate_cb(). + * @pre webrtc_media_packet_source_set_format() must be called if @a webrtc has a media packet source. + * @pre @a webrtc state must be set to #WEBRTC_STATE_IDLE. + * @post @a webrtc state is #WEBRTC_STATE_NEGOTIATING. + * @see webrtc_create() + * @see webrtc_stop() + */ +int webrtc_start_sync(webrtc_h webrtc); + /** * @internal * @brief Creates a signaling server for private network. diff --git a/include/webrtc_private.h b/include/webrtc_private.h index e80946ba..65e25200 100644 --- a/include/webrtc_private.h +++ b/include/webrtc_private.h @@ -501,6 +501,8 @@ typedef struct _webrtc_s { guint stats_timer_src; GMutex mutex; + GMutex state_mutex; + GCond state_cond; GMutex event_src_mutex; GMutex desc_mutex; GCond desc_cond; @@ -527,6 +529,7 @@ typedef struct _webrtc_s { webrtc_state_e state; webrtc_state_e pend_state; bool is_destroying; + bool is_start_sync; GList *signals; diff --git a/packaging/capi-media-webrtc.spec b/packaging/capi-media-webrtc.spec index c00160f3..82e389b4 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.4.45 +Version: 0.4.46 Release: 0 Group: Multimedia/API License: Apache-2.0 diff --git a/src/webrtc.c b/src/webrtc.c index 3d33fba7..30318771 100644 --- a/src/webrtc.c +++ b/src/webrtc.c @@ -94,6 +94,8 @@ int webrtc_create(webrtc_h *webrtc) g_mutex_init(&_webrtc->mutex); locker = g_mutex_locker_new(&_webrtc->mutex); + g_mutex_init(&_webrtc->state_mutex); + g_cond_init(&_webrtc->state_cond); g_mutex_init(&_webrtc->event_src_mutex); g_mutex_init(&_webrtc->desc_mutex); g_cond_init(&_webrtc->desc_cond); @@ -202,6 +204,8 @@ int webrtc_destroy(webrtc_h webrtc) LOG_INFO("webrtc[%p] is destroyed", webrtc); g_mutex_clear(&_webrtc->destroy_mutex); + g_cond_clear(&_webrtc->state_cond); + g_mutex_clear(&_webrtc->state_mutex); g_clear_pointer(&locker, g_mutex_locker_free); g_mutex_clear(&_webrtc->mutex); @@ -228,11 +232,8 @@ int webrtc_start(webrtc_h webrtc) RET_VAL_IF(!_check_if_codec_is_set_to_null_sources(_webrtc), WEBRTC_ERROR_INVALID_OPERATION, "transceiver codec is should be set"); #ifndef TIZEN_TV - ret = _acquire_resource_if_needed(_webrtc); - if (ret != WEBRTC_ERROR_NONE) { - LOG_ERROR("failed to acquire resource, webrtc[%p]", _webrtc); + if ((ret = _acquire_resource_if_needed(_webrtc)) != WEBRTC_ERROR_NONE) return ret; - } #endif ret = _complete_sources(_webrtc); RET_VAL_IF(ret != WEBRTC_ERROR_NONE, ret, "failed to complete sources"); @@ -244,7 +245,6 @@ int webrtc_start(webrtc_h webrtc) LOG_INFO("webrtc[%p] is started", webrtc); - return WEBRTC_ERROR_NONE; } diff --git a/src/webrtc_internal.c b/src/webrtc_internal.c index 365cec94..8cbd8df2 100644 --- a/src/webrtc_internal.c +++ b/src/webrtc_internal.c @@ -386,4 +386,56 @@ int webrtc_get_rtp_packet_drop_probability(webrtc_h webrtc, bool sender, float * return _get_packet_drop_probability(webrtc, sender, probability); } + +int webrtc_start_sync(webrtc_h webrtc) +{ + int ret = WEBRTC_ERROR_NONE; + g_autoptr(GMutexLocker) locker = NULL; + webrtc_s *_webrtc = (webrtc_s *)webrtc; + gint64 end_time; + + RET_VAL_IF(_webrtc == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "webrtc is NULL"); + + locker = g_mutex_locker_new(&_webrtc->mutex); + + RET_VAL_IF(_webrtc->ice_candidate_cb.callback == NULL, WEBRTC_ERROR_INVALID_OPERATION, "the ice candidate callback should be set"); + RET_VAL_IF(_webrtc->state != WEBRTC_STATE_IDLE, WEBRTC_ERROR_INVALID_STATE, "the state should be IDLE"); + RET_VAL_IF(_webrtc->gst.webrtcbin == NULL, WEBRTC_ERROR_INVALID_OPERATION, "webrtcbin is NULL"); + RET_VAL_IF(!_check_if_format_is_set_to_packet_sources(_webrtc), WEBRTC_ERROR_INVALID_OPERATION, "the media format should be set"); + RET_VAL_IF(!_check_if_path_is_set_to_file_sources(_webrtc), WEBRTC_ERROR_INVALID_OPERATION, "the media path should be set"); + RET_VAL_IF(!_check_if_codec_is_set_to_null_sources(_webrtc), WEBRTC_ERROR_INVALID_OPERATION, "transceiver codec is should be set"); + +#ifndef TIZEN_TV + if ((ret = _acquire_resource_if_needed(_webrtc)) != WEBRTC_ERROR_NONE) + return ret; +#endif + ret = _complete_sources(_webrtc); + RET_VAL_IF(ret != WEBRTC_ERROR_NONE, ret, "failed to complete sources"); + + g_mutex_lock(&_webrtc->state_mutex); + + _webrtc->is_start_sync = true; + _webrtc->pend_state = WEBRTC_STATE_NEGOTIATING; + + if ((ret = _gst_pipeline_set_state(_webrtc, GST_STATE_PLAYING)) != WEBRTC_ERROR_NONE) { + _webrtc->pend_state = WEBRTC_STATE_IDLE; + goto out; + } + + end_time = g_get_monotonic_time() + 10 * G_TIME_SPAN_SECOND; + LOG_DEBUG("wait..."); + if (!g_cond_wait_until(&_webrtc->state_cond, &_webrtc->state_mutex, end_time)) { + LOG_ERROR("timeout of g_cond_wait_until()"); + _webrtc->pend_state = WEBRTC_STATE_IDLE; + ret = WEBRTC_ERROR_INVALID_OPERATION; + goto out; + } + + LOG_INFO("webrtc[%p] is started", webrtc); + +out: + _webrtc->is_start_sync = false; + g_mutex_unlock(&_webrtc->state_mutex); + return ret; +} //LCOV_EXCL_STOP diff --git a/src/webrtc_private.c b/src/webrtc_private.c index 36981e63..8dcb4d6d 100644 --- a/src/webrtc_private.c +++ b/src/webrtc_private.c @@ -1122,7 +1122,14 @@ static void __webrtcbin_on_negotiation_needed_cb(GstElement *webrtcbin, gpointer RET_IF(webrtc == NULL, "webrtc is NULL"); - _post_state_cb_in_idle(webrtc, WEBRTC_STATE_NEGOTIATING); + if (webrtc->is_start_sync) { + webrtc->state = WEBRTC_STATE_NEGOTIATING; + g_mutex_lock(&webrtc->state_mutex); + g_cond_signal(&webrtc->state_cond); + g_mutex_unlock(&webrtc->state_mutex); + } else { + _post_state_cb_in_idle(webrtc, WEBRTC_STATE_NEGOTIATING); + } if (webrtc->negotiation_needed_cb.callback == NULL) { LOG_DEBUG("negotiation_needed_cb is NULL, skip it");