Make webrtc_foreach_stats() synchronous function 19/279619/2
authorSangchul Lee <sc11.lee@samsung.com>
Fri, 12 Aug 2022 09:02:03 +0000 (18:02 +0900)
committerSangchul Lee <sc11.lee@samsung.com>
Fri, 12 Aug 2022 09:12:53 +0000 (18:12 +0900)
It ensures that webrtc_foreach_stats() returns after invoking
all callbacks. It takes approximately under 30ms.

[Version] 0.3.202
[Issue Type] API

Change-Id: I5502ee3e948bad506279e34ba949bf99c5ed934c
Signed-off-by: Sangchul Lee <sc11.lee@samsung.com>
include/webrtc.h
include/webrtc_private.h
packaging/capi-media-webrtc.spec
src/webrtc.c
src/webrtc_stats.c

index 3cc748c44d2fa09e32bfc0baf67edf6cc2288373..8332409d7b6f130eabd798830cb0f7f050425a16 100644 (file)
@@ -2783,7 +2783,7 @@ int webrtc_data_channel_unset_buffered_amount_low_cb(webrtc_data_channel_h chann
 */
 
 /**
- * @brief Retrieves all the statistics properties, asynchronously.
+ * @brief Retrieves all the statistics properties.
  * @since_tizen 7.0
  * @remarks The registered callback will be invoked in an internal thread of the webrtc.
  * @param[in] webrtc      WebRTC handle
index 43b0a778e58545964f8d30b4afa4190d9cd7edbd..9a89bd34d1fe32fbea61c14d1034256221244ec3 100644 (file)
@@ -476,6 +476,8 @@ typedef struct _webrtc_s {
        GMutex event_src_mutex;
        GMutex desc_mutex;
        GCond desc_cond;
+       GMutex stats_mutex;
+       GCond stats_cond;
 
        webrtc_gst_s gst;
        unsigned int payload_types;
@@ -767,7 +769,7 @@ int _data_channel_send_string(webrtc_data_channel_s *channel, const char *string
 int _data_channel_send_bytes(webrtc_data_channel_s *channel, const char *data, unsigned int size);
 
 /* stats */
-void _webrtcbin_get_stats(webrtc_s *webrtc, int type_mask, void *callback, void *user_data);
+void _webrtcbin_foreach_stats(webrtc_s *webrtc, int type_mask, void *callback, void *user_data);
 void _set_stats_timer(webrtc_s *webrtc);
 void _unset_stats_timer(webrtc_s *webrtc);
 void _init_stats_all_fields_list(void);
index 758ca9cd827d85e2f950a1ab12589464af5ccca4..cf76a5661a700b869b1c4fb4e3e1e78ddce87152 100644 (file)
@@ -1,6 +1,6 @@
 Name:       capi-media-webrtc
 Summary:    A WebRTC library in Tizen Native API
-Version:    0.3.201
+Version:    0.3.202
 Release:    0
 Group:      Multimedia/API
 License:    Apache-2.0
index 061cabf24cb0da8b80b94b126dc14e950977ba79..c92e2e3ced208d220b48dc1a31ead369f973d98f 100644 (file)
@@ -95,6 +95,8 @@ int webrtc_create(webrtc_h *webrtc)
        g_mutex_init(&_webrtc->event_src_mutex);
        g_mutex_init(&_webrtc->desc_mutex);
        g_cond_init(&_webrtc->desc_cond);
+       g_mutex_init(&_webrtc->stats_mutex);
+       g_cond_init(&_webrtc->stats_cond);
 
        _load_ini(_webrtc);
        if (_is_resource_required(&_webrtc->ini)) {
@@ -159,6 +161,8 @@ int webrtc_destroy(webrtc_h webrtc)
        _gst_destroy_pipeline(_webrtc);
        _unload_ini(_webrtc);
 
+       g_cond_clear(&_webrtc->stats_cond);
+       g_mutex_clear(&_webrtc->stats_mutex);
        g_cond_clear(&_webrtc->desc_cond);
        g_mutex_clear(&_webrtc->desc_mutex);
        g_mutex_clear(&_webrtc->event_src_mutex);
@@ -2014,7 +2018,7 @@ int webrtc_foreach_stats(webrtc_h webrtc, int type_mask, webrtc_stats_cb callbac
 
        RET_VAL_IF(_webrtc->state != WEBRTC_STATE_PLAYING, WEBRTC_ERROR_INVALID_STATE, "the state should be PLAYING");
 
-       _webrtcbin_get_stats(_webrtc, type_mask, callback, user_data);
+       _webrtcbin_foreach_stats(_webrtc, type_mask, callback, user_data);
 
        LOG_INFO("webrtc[%p] type_mask[0x%x] callback[%p] user_data[%p]", webrtc, type_mask, callback, user_data);
 
index ef50d7b4ea454a0c0ec0cac95ef1c59f4f60b3c1..d80091003233fcb23c6f9336b991e53743ca60a4 100644 (file)
@@ -18,6 +18,7 @@
 #include "webrtc_private.h"
 
 //LCOV_EXCL_START
+#define FOREACH_STATS_TIMEOUT_SEC       1
 #define WEBRTC_STATS_TYPE_GST_ALL       0xFFFF /* All statistics types of webrtcbin for debugging */
 #define WEBRTC_STATS_PROP_NOT_EXPORTED  0x0    /* Statistics property that should not be exported */
 
@@ -316,10 +317,12 @@ static gboolean __invoke_stats_cb(int type, const gchar *field_name, webrtc_stat
                return TRUE;
        }
 
+       LOG_DEBUG(">>> type[0x%04x], callback[%p], user_data[%p]", type, stats_cb->callback, stats_cb->user_data);
        if (!((webrtc_stats_cb)stats_cb->callback)(type, &prop_info, stats_cb->user_data)) {
                LOG_DEBUG("stats foreach callback[%p] returns false, stop it", stats_cb->callback);
                return FALSE;
        }
+       LOG_DEBUG("<<< end of the callback");
 
        return TRUE;
 }
@@ -717,6 +720,7 @@ static gboolean __webrtcbin_stats_cb(GQuark field_id, const GValue *value, gpoin
 static void __webrtcbin_get_stats_cb(GstPromise *promise, gpointer user_data)
 {
        const GstStructure *stats;
+       promise_userdata_s *data = (promise_userdata_s *)user_data;
 
        RET_IF(gst_promise_wait(promise) != GST_PROMISE_RESULT_REPLIED, "failed to gst_promise_wait()");
        RET_IF(user_data == NULL, "user_data is NULL");
@@ -725,16 +729,23 @@ static void __webrtcbin_get_stats_cb(GstPromise *promise, gpointer user_data)
        RET_IF(stats == NULL, "failed to gst_promise_get_reply()");
 
        gst_structure_foreach(stats, __webrtcbin_stats_cb, user_data);
+
+       g_mutex_lock(&data->webrtc->stats_mutex);
+       g_cond_signal(&data->webrtc->stats_cond);
+       g_mutex_unlock(&data->webrtc->stats_mutex);
 }
 
-void _webrtcbin_get_stats(webrtc_s *webrtc, int type_mask, void *callback, void *user_data)
+void _webrtcbin_foreach_stats(webrtc_s *webrtc, int type_mask, void *callback, void *user_data)
 {
        GstPromise *promise;
        promise_userdata_s *userdata;
+       gint64 end_time = g_get_monotonic_time() + FOREACH_STATS_TIMEOUT_SEC * G_TIME_SPAN_SECOND;
 
        RET_IF(webrtc == NULL, "webrtc is NULL");
        RET_IF(webrtc->gst.webrtcbin == NULL, "webrtcbin is NULL");
 
+       g_mutex_lock(&webrtc->stats_mutex);
+
        userdata = g_new0(promise_userdata_s, 1);
        userdata->webrtc = webrtc;
        userdata->type_mask = type_mask;
@@ -749,6 +760,10 @@ void _webrtcbin_get_stats(webrtc_s *webrtc, int type_mask, void *callback, void
        LOG_DEBUG("emitting 'get-stats' on %p", webrtc->gst.webrtcbin);
 
        gst_promise_unref(promise);
+
+       if (!g_cond_wait_until(&webrtc->stats_cond, &webrtc->stats_mutex, end_time))
+               LOG_ERROR("failed to get stats within %d sec. of timeout", FOREACH_STATS_TIMEOUT_SEC);
+       g_mutex_unlock(&webrtc->stats_mutex);
 }
 
 static gboolean __get_stats_periodically(gpointer user_data)
@@ -756,7 +771,7 @@ static gboolean __get_stats_periodically(gpointer user_data)
        webrtc_s *webrtc = (webrtc_s *)user_data;
 
        if (webrtc->state == WEBRTC_STATE_PLAYING)
-               _webrtcbin_get_stats(webrtc, WEBRTC_STATS_TYPE_GST_ALL, NULL, NULL);
+               _webrtcbin_foreach_stats(webrtc, WEBRTC_STATS_TYPE_GST_ALL, NULL, NULL);
 
        return G_SOURCE_CONTINUE;
 }