NULL
};
-typedef struct _stats_userdata_s {
+/* Note that stats_type_mask_e below follows GstWebRTCStatsType of webrtc_fwd.h */
+typedef enum {
+ STATS_TYPE_ALL_MASK = 0xFFFF,
+ STATS_TYPE_CODEC_MASK = 0x0001,
+ STATS_TYPE_INBOUND_RTP_MASK = 0x0002,
+ STATS_TYPE_OUTBOUND_RTP_MASK = 0x0004,
+ STATS_TYPE_REMOTE_INBOUND_RTP_MASK = 0x0008,
+ STATS_TYPE_REMOTE_OUTBOUND_RTP_MASK = 0x0010,
+ STATS_TYPE_CSRC_MASK = 0x0020,
+ STATS_TYPE_PEER_CONNECTION_MASK = 0x0040,
+ STATS_TYPE_DATA_CHANNEL_MASK = 0x0080,
+ STATS_TYPE_STREAM_MASK = 0x0100,
+ STATS_TYPE_TRANSPORT_MASK = 0x0200,
+ STATS_TYPE_CANDIDATE_PAIR_MASK = 0x0400,
+ STATS_TYPE_LOCAL_CANDIDATE_MASK = 0x0800,
+ STATS_TYPE_REMOTE_CANDIDATE_MASK = 0x1000,
+ STATS_TYPE_CERTIFICATE_MASK = 0x2000,
+} stats_type_mask_e;
+
+typedef struct _promise_userdata_s {
webrtc_s *webrtc;
int type_mask;
+ webrtc_callbacks_s stats_cb;
+} promise_userdata_s;
+
+typedef struct _stats_userdata_s {
+ promise_userdata_s *p_userdata;
+ stats_type_mask_e type;
stats_field_s **fields_list;
} stats_userdata_s;
-static gboolean __gststructure_foreach_cb(GQuark field_id, const GValue *val, gpointer user_data)
+static gboolean __stats_field_foreach_cb(GQuark field_id, const GValue *val, gpointer user_data)
{
stats_userdata_s *stats = (stats_userdata_s *)user_data;
int i, j;
RET_VAL_IF(user_data == NULL, FALSE, "user_data is NULL");
- RET_VAL_IF(stats->webrtc == NULL, FALSE, "webrtc is NULL");
+ RET_VAL_IF(stats->p_userdata == NULL, FALSE, "p_userdata is NULL");
+ RET_VAL_IF(stats->p_userdata->webrtc == NULL, FALSE, "webrtc is NULL");
RET_VAL_IF(stats->fields_list == NULL, FALSE, "fields_list is NULL");
/* Note that it only allow fields pre-defined in list */
return TRUE;
}
-static void __stats_codec_invoke_callback(const GstStructure *s, stats_userdata_s *user_data)
+static void __stats_codec_invoke_callback(const GstStructure *s, stats_type_mask_e type_mask, stats_field_s **fields_list, promise_userdata_s *user_data)
{
+ stats_userdata_s stats_userdata = { .p_userdata = user_data, .type = type_mask, .fields_list = fields_list };
+
RET_IF(user_data == NULL, "user_data is NULL");
LOG_DEBUG_ENTER();
- gst_structure_foreach(s, __gststructure_foreach_cb, user_data);
+ gst_structure_foreach(s, __stats_field_foreach_cb, &stats_userdata);
}
-static void __stats_inbound_rtp_invoke_callback(const GstStructure *s, stats_userdata_s *user_data)
+static void __stats_inbound_rtp_invoke_callback(const GstStructure *s, stats_type_mask_e type_mask, stats_field_s **fields_list, promise_userdata_s *user_data)
{
+ stats_userdata_s stats_userdata = { .p_userdata = user_data, .type = type_mask, .fields_list = fields_list };
GstStructure *rtpjitterbuffer_stats;
GstStructure *rtpsource_stats;
LOG_DEBUG_ENTER();
- gst_structure_foreach(s, __gststructure_foreach_cb, user_data);
+ gst_structure_foreach(s, __stats_field_foreach_cb, &stats_userdata);
gst_structure_get(s,
"gst-rtpjitterbuffer-stats", GST_TYPE_STRUCTURE, &rtpjitterbuffer_stats,
"gst-rtpsource-stats", GST_TYPE_STRUCTURE, &rtpsource_stats,
NULL);
LOG_DEBUG("gst-rtpjitterbuffer-stats ---> ");
- gst_structure_foreach(rtpjitterbuffer_stats, __gststructure_foreach_cb, user_data);
+ gst_structure_foreach(rtpjitterbuffer_stats, __stats_field_foreach_cb, &stats_userdata);
LOG_DEBUG("gst-rtpsource-stats ---> ");
- gst_structure_foreach(rtpsource_stats, __gststructure_foreach_cb, user_data);
+ gst_structure_foreach(rtpsource_stats, __stats_field_foreach_cb, &stats_userdata);
}
-static void __stats_outbound_rtp_invoke_callback(const GstStructure *s, stats_userdata_s *user_data)
+static void __stats_outbound_rtp_invoke_callback(const GstStructure *s, stats_type_mask_e type_mask, stats_field_s **fields_list, promise_userdata_s *user_data)
{
+ stats_userdata_s stats_userdata = { .p_userdata = user_data, .type = type_mask, .fields_list = fields_list };
GstStructure *rtpsource_stats;
RET_IF(user_data == NULL, "user_data is NULL");
LOG_DEBUG_ENTER();
- gst_structure_foreach(s, __gststructure_foreach_cb, user_data);
+ gst_structure_foreach(s, __stats_field_foreach_cb, &stats_userdata);
gst_structure_get(s, "gst-rtpsource-stats", GST_TYPE_STRUCTURE, &rtpsource_stats, NULL);
LOG_DEBUG("gst-rtpsource-stats ---> ");
- gst_structure_foreach(rtpsource_stats, __gststructure_foreach_cb, user_data);
+ gst_structure_foreach(rtpsource_stats, __stats_field_foreach_cb, &stats_userdata);
}
-static void __stats_remote_inbound_rtp_invoke_callback(const GstStructure *s, stats_userdata_s *user_data)
+static void __stats_remote_inbound_rtp_invoke_callback(const GstStructure *s, stats_type_mask_e type_mask, stats_field_s **fields_list, promise_userdata_s *user_data)
{
+ stats_userdata_s stats_userdata = { .p_userdata = user_data, .type = type_mask, .fields_list = fields_list };
RET_IF(user_data == NULL, "user_data is NULL");
LOG_DEBUG_ENTER();
/* FIXME: type of 'packets-lost(int)' should be fixed.*/
- gst_structure_foreach(s, __gststructure_foreach_cb, user_data);
+ gst_structure_foreach(s, __stats_field_foreach_cb, &stats_userdata);
}
-static void __stats_remote_outbound_rtp_invoke_callback(const GstStructure *s, stats_userdata_s *user_data)
+static void __stats_remote_outbound_rtp_invoke_callback(const GstStructure *s, stats_type_mask_e type_mask, stats_field_s **fields_list, promise_userdata_s *user_data)
{
+ stats_userdata_s stats_userdata = { .p_userdata = user_data, .type = type_mask, .fields_list = fields_list };
RET_IF(user_data == NULL, "user_data is NULL");
LOG_DEBUG_ENTER();
- gst_structure_foreach(s, __gststructure_foreach_cb, user_data);
+ gst_structure_foreach(s, __stats_field_foreach_cb, &stats_userdata);
}
-static void __stats_csrc_invoke_callback(const GstStructure *s, stats_userdata_s *user_data)
+static void __stats_csrc_invoke_callback(const GstStructure *s, stats_type_mask_e type_mask, stats_field_s **fields_list, promise_userdata_s *user_data)
{
+ stats_userdata_s stats_userdata = { .p_userdata = user_data, .type = type_mask, .fields_list = fields_list };
RET_IF(user_data == NULL, "user_data is NULL");
LOG_DEBUG_ENTER();
- gst_structure_foreach(s, __gststructure_foreach_cb, user_data);
+ gst_structure_foreach(s, __stats_field_foreach_cb, &stats_userdata);
/* not implemented */
}
-static void __stats_peer_connection_invoke_callback(const GstStructure *s, stats_userdata_s *user_data)
+static void __stats_peer_connection_invoke_callback(const GstStructure *s, stats_type_mask_e type_mask, stats_field_s **fields_list, promise_userdata_s *user_data)
{
+ stats_userdata_s stats_userdata = { .p_userdata = user_data, .type = type_mask, .fields_list = fields_list };
RET_IF(user_data == NULL, "user_data is NULL");
LOG_DEBUG_ENTER();
- gst_structure_foreach(s, __gststructure_foreach_cb, user_data);
+ gst_structure_foreach(s, __stats_field_foreach_cb, &stats_userdata);
}
-static void __stats_data_channel_invoke_callback(const GstStructure *s, stats_userdata_s *user_data)
+static void __stats_data_channel_invoke_callback(const GstStructure *s, stats_type_mask_e type_mask, stats_field_s **fields_list, promise_userdata_s *user_data)
{
+ stats_userdata_s stats_userdata = { .p_userdata = user_data, .type = type_mask, .fields_list = fields_list };
RET_IF(user_data == NULL, "user_data is NULL");
LOG_DEBUG_ENTER();
- gst_structure_foreach(s, __gststructure_foreach_cb, user_data);
+ gst_structure_foreach(s, __stats_field_foreach_cb, &stats_userdata);
/* not implemented */
}
-static void __stats_stream_invoke_callback(const GstStructure *s, stats_userdata_s *user_data)
+static void __stats_stream_invoke_callback(const GstStructure *s, stats_type_mask_e type_mask, stats_field_s **fields_list, promise_userdata_s *user_data)
{
+ stats_userdata_s stats_userdata = { .p_userdata = user_data, .type = type_mask, .fields_list = fields_list };
RET_IF(user_data == NULL, "user_data is NULL");
LOG_DEBUG_ENTER();
- gst_structure_foreach(s, __gststructure_foreach_cb, user_data);
+ gst_structure_foreach(s, __stats_field_foreach_cb, &stats_userdata);
/* not implemented */
}
-static void __stats_transport_invoke_callback(const GstStructure *s, stats_userdata_s *user_data)
+static void __stats_transport_invoke_callback(const GstStructure *s, stats_type_mask_e type_mask, stats_field_s **fields_list, promise_userdata_s *user_data)
{
+ stats_userdata_s stats_userdata = { .p_userdata = user_data, .type = type_mask, .fields_list = fields_list };
RET_IF(user_data == NULL, "user_data is NULL");
LOG_DEBUG_ENTER();
- gst_structure_foreach(s, __gststructure_foreach_cb, user_data);
+ gst_structure_foreach(s, __stats_field_foreach_cb, &stats_userdata);
}
-static void __stats_candidate_pair_invoke_callback(const GstStructure *s, stats_userdata_s *user_data)
+static void __stats_candidate_pair_invoke_callback(const GstStructure *s, stats_type_mask_e type_mask, stats_field_s **fields_list, promise_userdata_s *user_data)
{
+ stats_userdata_s stats_userdata = { .p_userdata = user_data, .type = type_mask, .fields_list = fields_list };
RET_IF(user_data == NULL, "user_data is NULL");
LOG_DEBUG_ENTER();
- gst_structure_foreach(s, __gststructure_foreach_cb, user_data);
+ gst_structure_foreach(s, __stats_field_foreach_cb, &stats_userdata);
/* not implemented */
}
-static void __stats_local_candidate_invoke_callback(const GstStructure *s, stats_userdata_s *user_data)
+static void __stats_local_candidate_invoke_callback(const GstStructure *s, stats_type_mask_e type_mask, stats_field_s **fields_list, promise_userdata_s *user_data)
{
+ stats_userdata_s stats_userdata = { .p_userdata = user_data, .type = type_mask, .fields_list = fields_list };
RET_IF(user_data == NULL, "user_data is NULL");
LOG_DEBUG_ENTER();
- gst_structure_foreach(s, __gststructure_foreach_cb, user_data);
+ gst_structure_foreach(s, __stats_field_foreach_cb, &stats_userdata);
/* not implemented */
}
-static void __stats_remote_candidate_invoke_callback(const GstStructure *s, stats_userdata_s *user_data)
+static void __stats_remote_candidate_invoke_callback(const GstStructure *s, stats_type_mask_e type_mask, stats_field_s **fields_list, promise_userdata_s *user_data)
{
+ stats_userdata_s stats_userdata = { .p_userdata = user_data, .type = type_mask, .fields_list = fields_list };
RET_IF(user_data == NULL, "user_data is NULL");
LOG_DEBUG_ENTER();
- gst_structure_foreach(s, __gststructure_foreach_cb, user_data);
+ gst_structure_foreach(s, __stats_field_foreach_cb, &stats_userdata);
/* not implemented */
}
-static void __stats_certificate_invoke_callback(const GstStructure *s, stats_userdata_s *user_data)
+static void __stats_certificate_invoke_callback(const GstStructure *s, stats_type_mask_e type_mask, stats_field_s **fields_list, promise_userdata_s *user_data)
{
+ stats_userdata_s stats_userdata = { .p_userdata = user_data, .type = type_mask, .fields_list = fields_list };
RET_IF(user_data == NULL, "user_data is NULL");
LOG_DEBUG_ENTER();
- gst_structure_foreach(s, __gststructure_foreach_cb, user_data);
+ gst_structure_foreach(s, __stats_field_foreach_cb, &stats_userdata);
/* not implemented */
}
-typedef void (*stats_func)(const GstStructure *s, stats_userdata_s *user_data);
-
-/* Note that stats_type_mask_e below follows GstWebRTCStatsType of webrtc_fwd.h */
-typedef enum {
- STATS_TYPE_ALL_MASK = 0xFFFF,
- STATS_TYPE_CODEC_MASK = 0x0001,
- STATS_TYPE_INBOUND_RTP_MASK = 0x0002,
- STATS_TYPE_OUTBOUND_RTP_MASK = 0x0004,
- STATS_TYPE_REMOTE_INBOUND_RTP_MASK = 0x0008,
- STATS_TYPE_REMOTE_OUTBOUND_RTP_MASK = 0x0010,
- STATS_TYPE_CSRC_MASK = 0x0020,
- STATS_TYPE_PEER_CONNECTION_MASK = 0x0040,
- STATS_TYPE_DATA_CHANNEL_MASK = 0x0080,
- STATS_TYPE_STREAM_MASK = 0x0100,
- STATS_TYPE_TRANSPORT_MASK = 0x0200,
- STATS_TYPE_CANDIDATE_PAIR_MASK = 0x0400,
- STATS_TYPE_LOCAL_CANDIDATE_MASK = 0x0800,
- STATS_TYPE_REMOTE_CANDIDATE_MASK = 0x1000,
- STATS_TYPE_CERTIFICATE_MASK = 0x2000,
-} stats_type_mask_e;
+typedef void (*stats_func)(const GstStructure *s, stats_type_mask_e type_mask, stats_field_s **fields_list, promise_userdata_s *user_data);
typedef struct {
stats_func func;
static gboolean __webrtcbin_stats_cb(GQuark field_id, const GValue *value, gpointer user_data)
{
- stats_userdata_s *stats_userdata = (stats_userdata_s *)user_data;
+ promise_userdata_s *userdata = (promise_userdata_s *)user_data;
const GstStructure *s;
GstWebRTCStatsType type;
- RET_VAL_IF(stats_userdata == NULL, TRUE, "stats_userdata is NULL");
+ RET_VAL_IF(userdata == NULL, TRUE, "userdata is NULL");
if (GST_VALUE_HOLDS_STRUCTURE(value)) {
s = gst_value_get_structure(value);
RET_VAL_IF((type < GST_WEBRTC_STATS_CODEC || type > GST_WEBRTC_STATS_CERTIFICATE),
TRUE, "invalid type(%u)", type);
- if (!(stats_userdata->type_mask & parse_stats[type].type_mask)) {
- LOG_DEBUG("skip this type[%u], type_mask[0x%x]", type, stats_userdata->type_mask);
+ if (!(userdata->type_mask & parse_stats[type].type_mask)) {
+ LOG_DEBUG("skip this type[%u], type_mask[0x%x]", type, userdata->type_mask);
return TRUE;
}
- stats_userdata->fields_list = parse_stats[type].fields_list;
- parse_stats[type].func(s, stats_userdata);
+ parse_stats[type].func(s, parse_stats[type].type_mask, parse_stats[type].fields_list, userdata);
} else {
LOG_ERROR("unknown field \'%s\' value type: \'%s\'",
RET_IF(stats == NULL, "failed to gst_promise_get_reply()");
gst_structure_foreach(stats, __webrtcbin_stats_cb, user_data);
-
- g_free(user_data);
}
-void _webrtcbin_get_stats(webrtc_s *webrtc, int type_mask)
+void _webrtcbin_get_stats(webrtc_s *webrtc, int type_mask, void *callback, void *user_data)
{
GstPromise *promise;
- stats_userdata_s *stats_userdata;
+ promise_userdata_s *userdata;
RET_IF(webrtc == NULL, "webrtc is NULL");
RET_IF(webrtc->gst.webrtcbin == NULL, "webrtcbin is NULL");
- stats_userdata = g_new0(stats_userdata_s, 1);
- stats_userdata->webrtc = webrtc;
- stats_userdata->type_mask = type_mask;
+ userdata = g_new0(promise_userdata_s, 1);
+ userdata->webrtc = webrtc;
+ userdata->type_mask = type_mask;
+ if (callback) {
+ userdata->stats_cb.callback = callback;
+ userdata->stats_cb.user_data = user_data;
+ }
- promise = gst_promise_new_with_change_func((GstPromiseChangeFunc)__webrtcbin_get_stats_cb, stats_userdata, NULL);
+ promise = gst_promise_new_with_change_func((GstPromiseChangeFunc)__webrtcbin_get_stats_cb, userdata, g_free);
g_signal_emit_by_name(webrtc->gst.webrtcbin, "get-stats", NULL, promise);
LOG_DEBUG("emitting 'get-stats' on %p", webrtc->gst.webrtcbin);
webrtc_s *webrtc = (webrtc_s *)user_data;
if (webrtc->state == WEBRTC_STATE_PLAYING)
- _webrtcbin_get_stats(webrtc, STATS_TYPE_ALL_MASK);
+ _webrtcbin_get_stats(webrtc, STATS_TYPE_ALL_MASK, NULL, NULL);
return G_SOURCE_CONTINUE;
}
if (__stats_all_fields_list[i][j].id == 0)
__stats_all_fields_list[i][j].id = g_quark_from_string(__stats_all_fields_list[i][j].name);
}
-//LCOV_EXCL_STOP
\ No newline at end of file
+//LCOV_EXCL_STOP