GMutex event_src_mutex;
GMutex desc_mutex;
GCond desc_cond;
+ GMutex stats_mutex;
+ GCond stats_cond;
webrtc_gst_s gst;
unsigned int payload_types;
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);
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)) {
_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);
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);
#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 */
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;
}
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");
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;
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)
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;
}