webrtc_internal: Add webrtc_start_sync() function 35/306935/2
authorSangchul Lee <sc11.lee@samsung.com>
Thu, 29 Feb 2024 02:40:47 +0000 (11:40 +0900)
committerSangchul Lee <sc11.lee@samsung.com>
Mon, 4 Mar 2024 06:38:04 +0000 (15:38 +0900)
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 <sc11.lee@samsung.com>
include/webrtc_internal.h
include/webrtc_private.h
packaging/capi-media-webrtc.spec
src/webrtc.c
src/webrtc_internal.c
src/webrtc_private.c

index c3d7755cf21c7f0448481d2bb8845f9054752b48..8c72075f5419e94521193c49ebbcf7e7767dc523 100644 (file)
@@ -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.
index e80946ba7931e5014a926e68d3521c633fbbc006..65e252004865a8417317dab38d9896a9d8695133 100644 (file)
@@ -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;
 
index c00160f3df717961b4320b1bf02bc751ffb35b63..82e389b4b180131d3707e6efd103e5276dec7b52 100644 (file)
@@ -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
index 3d33fba749c9afdbf4bff082e00ea0c1d11904b3..3031877176f04e3097046055b93f2fa1e2568ffb 100644 (file)
@@ -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;
 }
 
index 365cec94ddc38df4106795b6da127a861cf9cc4f..8cbd8df2a4d94209df5d38fcb72cf97327d5628e 100644 (file)
@@ -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
index 36981e637b123779ecfcb080ad89349af67831b1..8dcb4d6dfeaefab959636ce855294696cafa9f44 100644 (file)
@@ -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");