WEBRTC_DATA_CHANNEL_TYPE_BYTES, /**< Bytes data */
} webrtc_data_channel_type_e;
+/**
+ * @}
+ */
+
+/**
+* @addtogroup CAPI_MEDIA_WEBRTC_STATISTICS_MODULE
+* @{
+*/
+
+/**
+ * @brief Enumeration for WebRTC statistics type.
+ * @since_tizen 7.0
+ */
+typedef enum {
+ WEBRTC_STATS_TYPE_CODEC = 0x0001, /**< Codec */
+} webrtc_stats_type_e;
+
+/**
+ * @brief Definition for all the supported statistics types mask.
+ * @since_tizen 7.0
+ * @see webrtc_foreach_stats()
+ */
+#define WEBRTC_STATS_TYPE_ALL WEBRTC_STATS_TYPE_CODEC
+
+/**
+ * @brief Definition for mask value used by #webrtc_stats_prop_e that represents properties of rtc stats.
+ * @since_tizen 7.0
+ * @remarks It corresponds with the values described in https://www.w3.org/TR/webrtc-stats/#dom-rtcstats.
+ * @see webrtc_stats_prop_e
+ */
+#define WEBRTC_STATS_COMMON 0x00000100
+
+/**
+ * @brief Definition for mask value used by #webrtc_stats_prop_e that represents properties of rtc codec stats.
+ * @since_tizen 7.0
+ * @remarks It corresponds with the values described in https://www.w3.org/TR/webrtc-stats/#dom-rtccodecstats.
+ * @see webrtc_stats_prop_e
+ */
+#define WEBRTC_STATS_CODEC 0x00000200
+
+/**
+ * @brief Enumeration for WebRTC statistics property.
+ * @since_tizen 7.0
+ */
+typedef enum {
+ WEBRTC_STATS_PROP_TIMESTAMP = WEBRTC_STATS_COMMON | 0x01, /**< Timestamp */
+ WEBRTC_STATS_PROP_ID = WEBRTC_STATS_COMMON | 0x02, /**< Id */
+ WEBRTC_STATS_PROP_PAYLOAD_TYPE = WEBRTC_STATS_CODEC | 0x01, /**< Payload type */
+ WEBRTC_STATS_PROP_CLOCK_RATE = WEBRTC_STATS_CODEC | 0x02, /**< Clock rate */
+ WEBRTC_STATS_PROP_CHANNELS = WEBRTC_STATS_CODEC | 0x03, /**< Channels */
+ WEBRTC_STATS_PROP_MIME_TYPE = WEBRTC_STATS_CODEC | 0x04, /**< MIME type */
+ WEBRTC_STATS_PROP_CODEC_TYPE = WEBRTC_STATS_CODEC | 0x05, /**< Codec type */
+ WEBRTC_STATS_PROP_SDP_FMTP_LINE = WEBRTC_STATS_CODEC | 0x06, /**< SDP FMTP line */
+} webrtc_stats_prop_e;
+
+/**
+ * @brief Enumeration for statistics property data type.
+ * @since_tizen 7.0
+ */
+typedef enum {
+ WEBRTC_STATS_PROP_TYPE_BOOL, /**< Boolean type */
+ WEBRTC_STATS_PROP_TYPE_INT, /**< Signed integer type */
+ WEBRTC_STATS_PROP_TYPE_UINT, /**< Unsigned integer type */
+ WEBRTC_STATS_PROP_TYPE_INT64, /**< 64-bit signed integer type */
+ WEBRTC_STATS_PROP_TYPE_UINT64, /**< 64-bit unsigned integer type */
+ WEBRTC_STATS_PROP_TYPE_FLOAT, /**< Float type */
+ WEBRTC_STATS_PROP_TYPE_DOUBLE, /**< Double type */
+ WEBRTC_STATS_PROP_TYPE_STRING, /**< String type */
+} webrtc_stats_prop_type_e;
+
+/**
+ * @brief The structure type for statistics property information.
+ * @since_tizen 7.0
+ */
+typedef struct {
+ const char *name; /**< The property name */
+ webrtc_stats_prop_e prop; /**< The property enum */
+ webrtc_stats_prop_type_e type; /**< The property data type */
+ /** The property value as per the data type above */
+ union {
+ bool v_bool; /**< For boolean */
+ int v_int; /**< For signed integer */
+ unsigned int v_uint; /**< For unsigned integer */
+ int64_t v_int64; /**< For 64-bit signed integer */
+ uint64_t v_uint64; /**< For 64-bit unsigned integer */
+ float v_float; /**< For float */
+ double v_double; /**< For double */
+ const char *v_string; /**< For string */
+ };
+} webrtc_stats_prop_info_s;
+
/**
* @}
*/
* @see webrtc_data_channel_unset_buffered_amount_low_cb()
*/
typedef void (*webrtc_data_channel_buffered_amount_low_cb)(webrtc_data_channel_h channel, void *user_data);
+
+/**
+ * @}
+ */
+
+/**
+* @addtogroup CAPI_MEDIA_WEBRTC_STATISTICS_MODULE
+* @{
+*/
+
+/**
+ * @brief Called iteratively to inform about a statistics property.
+ * @since_tizen 7.0
+ * @param[in] type The statistics type
+ * @param[in] prop_info The statistics property information
+ * @param[in] user_data The user data passed from the callback registration function
+ * @return @c true to continue with the next iteration of the loop,
+ * otherwise @c false to break out of the loop
+ * @see webrtc_foreach_stats()
+ * @par Example
+ * @code
+ bool __stats_cb(webrtc_stats_type_e type, const webrtc_stats_prop_info_s *prop_info, void *user_data)
+ {
+ switch (prop_info->type) {
+ case WEBRTC_STATS_PROP_TYPE_BOOL:
+ printf("type[0x%x] prop[%s, 0x%08x, value:%d]\n", type, prop_info->name, prop_info->prop, prop_info->v_bool);
+ break;
+ case WEBRTC_STATS_PROP_TYPE_INT:
+ printf("type[0x%x] prop[%s, 0x%08x, value:%d]\n", type, prop_info->name, prop_info->prop, prop_info->v_int);
+ break;
+ case WEBRTC_STATS_PROP_TYPE_INT64:
+ printf("type[0x%x] prop[%s, 0x%08x, value:%"PRId64"]\n", type, prop_info->name, prop_info->prop, prop_info->v_int64);
+ break;
+ case WEBRTC_STATS_PROP_TYPE_UINT:
+ printf("type[0x%x] prop[%s, 0x%08x, value:%u]\n", type, prop_info->name, prop_info->prop, prop_info->v_uint);
+ break;
+ case WEBRTC_STATS_PROP_TYPE_UINT64:
+ printf("type[0x%x] prop[%s, 0x%08x, value:%"PRIu64"]\n", type, prop_info->name, prop_info->prop, prop_info->v_uint64);
+ break;
+ case WEBRTC_STATS_PROP_TYPE_FLOAT:
+ printf("type[0x%x] prop[%s, 0x%08x, value:%f]\n", type, prop_info->name, prop_info->prop, prop_info->v_float);
+ break;
+ case WEBRTC_STATS_PROP_TYPE_DOUBLE:
+ printf("type[0x%x] prop[%s, 0x%08x, value:%lf]\n", type, prop_info->name, prop_info->prop, prop_info->v_double);
+ break;
+ case WEBRTC_STATS_PROP_TYPE_STRING:
+ printf("type[0x%x] prop[%s, 0x%08x, value:%s]\n", type, prop_info->name, prop_info->prop, prop_info->v_string);
+ break;
+ }
+ return true;
+ }
+ * @endcode
+ */
+typedef bool (*webrtc_stats_cb)(webrtc_stats_type_e type, const webrtc_stats_prop_info_s *prop_info, void *user_data);
+
/**
* @}
*/
*/
int webrtc_data_channel_unset_buffered_amount_low_cb(webrtc_data_channel_h channel);
+/**
+ * @}
+ */
+
+/**
+* @addtogroup CAPI_MEDIA_WEBRTC_STATISTICS_MODULE
+* @{
+*/
+
+/**
+ * @brief Retrieves all the statistics properties, asynchronously.
+ * @since_tizen 7.0
+ * @remarks The registered callback will be invoked in an internal thread of the webrtc.
+ * @param[in] webrtc WebRTC handle
+ * @param[in] type_mask The mask values of #webrtc_stats_type_e combined with bitwise 'or'
+ * @param[in] callback Callback function pointer
+ * @param[in] user_data The user data to be passed to the callback function
+ * @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_STATE Invalid state
+ * @pre @a webrtc state must be set to #WEBRTC_STATE_PLAYING.
+ * @post webrtc_stats_cb() will be invoked.
+ */
+int webrtc_foreach_stats(webrtc_h webrtc, int type_mask, webrtc_stats_cb callback, void *user_data);
+
/**
* @}
*/
#include "webrtc_private.h"
//LCOV_EXCL_START
+#define WEBRTC_STATS_TYPE_GST_ALL 0xFFFF /* All statistic types of webrtcbin for debugging */
typedef struct _stats_field_s {
const gchar *name;
+ webrtc_stats_prop_e prop;
GQuark id;
} stats_field_s;
* "id" G_TYPE_STRING unique identifier
*/
static stats_field_s __stats_common_fields[] = {
- { "timestamp", 0 },
- { "type", 0 },
- { "id", 0 },
- { NULL, 0 }
+ { "timestamp", WEBRTC_STATS_PROP_TIMESTAMP, 0 },
+ { "type", 0, 0 },
+ { "id", WEBRTC_STATS_PROP_ID, 0 },
+ { NULL, 0, 0 }
};
/*
* "sdp-fmtp-line" G_TYPE_STRING the a=fmtp line in the SDP corresponding to the codec
*/
static stats_field_s __stats_codec_fields[] = {
- { "payload-type", 0 },
- { "clock-rate", 0 },
- { "ssrc", 0 },
- { "channels", 0 },
- { "mime-type", 0 },
- { "codec-type", 0 },
- { "sdp-fmtp-line", 0 },
- { NULL, 0 }
+ { "payload-type", WEBRTC_STATS_PROP_PAYLOAD_TYPE, 0 },
+ { "clock-rate", WEBRTC_STATS_PROP_CLOCK_RATE, 0 },
+ { "ssrc", 0, 0 },
+ { "channels", WEBRTC_STATS_PROP_CHANNELS, 0 },
+ { "mime-type", WEBRTC_STATS_PROP_MIME_TYPE, 0 },
+ { "codec-type", WEBRTC_STATS_PROP_CODEC_TYPE, 0 },
+ { "sdp-fmtp-line", WEBRTC_STATS_PROP_SDP_FMTP_LINE, 0 },
+ { NULL, 0, 0 }
};
/*
* "nack-count" G_TYPE_UINT NACK requests received by the sender (only for local statistics)
*/
static stats_field_s __stats_rtp_stream_fields[] = {
- { "ssrc", 0 },
- { "transport-id", 0 },
- { "codec-id", 0 },
- { "fir-count", 0 },
- { "pli-count", 0 },
- { "nack-count", 0 },
- { NULL, 0 }
+ { "ssrc", 0, 0 },
+ { "transport-id", 0, 0 },
+ { "codec-id", 0, 0 },
+ { "fir-count", 0, 0 },
+ { "pli-count", 0, 0 },
+ { "nack-count", 0, 0 },
+ { NULL, 0, 0 }
};
/*
* "jitter" G_TYPE_DOUBLE packet jitter measured in seconds
*/
static stats_field_s __stats_received_rtp_stream_fields[] = {
- { "packets-received", 0 },
- { "packets-lost", 0 },
- { "packets-discarded", 0 },
- { "packets-repaired", 0 },
- { "jitter", 0 },
- { NULL, 0 }
+ { "packets-received", 0, 0 },
+ { "packets-lost", 0, 0 },
+ { "packets-discarded", 0, 0 },
+ { "packets-repaired", 0, 0 },
+ { "jitter", 0, 0 },
+ { NULL, 0, 0 }
};
/*
* "remote-id" G_TYPE_STRING identifier for the associated RTCRemoteOutboundRTPStreamStats
*/
static stats_field_s __stats_inbound_rtp_stream_fields[] = {
- { "remote-id", 0 },
- { "bytes-received", 0 },
- { "packets-duplicated", 0 },
- { "fir-count", 0 },
- { "pli-count", 0 },
- { "nack-count", 0 },
- { NULL, 0 }
+ { "remote-id", 0, 0 },
+ { "bytes-received", 0, 0 },
+ { "packets-duplicated", 0, 0 },
+ { "fir-count", 0, 0 },
+ { "pli-count", 0, 0 },
+ { "nack-count", 0, 0 },
+ { NULL, 0, 0 }
};
/*
* "bytes-sent" G_TYPE_UINT64 number of packets sent (only for local outbound)
*/
static stats_field_s __stats_sent_rtp_stream_fields[] = {
- { "packets-sent", 0 },
- { "bytes-sent", 0 },
- { NULL, 0 }
+ { "packets-sent", 0, 0 },
+ { "bytes-sent", 0, 0 },
+ { NULL, 0, 0 }
};
/*
* "remote-id" G_TYPE_STRING identifier for the associated RTCRemoteInboundRTPSTreamStats
*/
static stats_field_s __stats_outbound_rtp_stream_fields[] = {
- { "remote-id", 0 },
- { NULL, 0 }
+ { "remote-id", 0, 0 },
+ { NULL, 0, 0 }
};
/*
* "fraction-lost" G_TYPE_DOUBLE the fraction packet loss reported for this SSRC
*/
static stats_field_s __stats_remote_inbound_rtp_stream_fields[] = {
- { "local-id", 0 },
- { "round-trip-time", 0 },
- { "fraction-lost", 0 },
- { NULL, 0 }
+ { "local-id", 0, 0 },
+ { "round-trip-time", 0, 0 },
+ { "fraction-lost", 0, 0 },
+ { NULL, 0, 0 }
};
/*
* "remote-timestamp" G_TYPE_DOUBLE the remote timestamp at which these statistics were sent by the remote endpoint
*/
static stats_field_s __stats_remote_outbound_rtp_stream_fields[] = {
- { "local-id", 0 },
- { "remote-timestamp", 0 },
- { NULL, 0 }
+ { "local-id", 0, 0 },
+ { "remote-timestamp", 0, 0 },
+ { NULL, 0, 0 }
};
/*
* "data-channels-accepted" G_TYPE_UINT the number of unique RTCDataChannels signaled in a ondatachannel event on the RTCPeerConnection
*/
static stats_field_s __stats_peer_connection_fields[] = {
- { "data-channels-opened", 0 },
- { "data-channels-closed", 0 },
- { "data-channels-requested", 0 },
- { "data-channels-accepted", 0 },
- { NULL, 0 }
+ { "data-channels-opened", 0, 0 },
+ { "data-channels-closed", 0, 0 },
+ { "data-channels-requested", 0, 0 },
+ { "data-channels-accepted", 0, 0 },
+ { NULL, 0, 0 }
};
static stats_field_s __stats_transport_fields[] = {
/* not supported yet */
- { NULL, 0 }
+ { NULL, 0, 0 }
};
static stats_field_s *__stats_all_fields_list[] = {
NULL
};
-/* 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;
typedef struct _stats_userdata_s {
promise_userdata_s *p_userdata;
- stats_type_mask_e type;
+ int type;
stats_field_s **fields_list;
} stats_userdata_s;
+static gboolean __invoke_stats_cb(int type, const gchar *field_name, webrtc_stats_prop_e prop, webrtc_stats_prop_type_e data_type, void *result, webrtc_callbacks_s *stats_cb)
+{
+ webrtc_stats_prop_info_s prop_info = { .name = field_name, .prop = prop, .type = data_type };
+
+ if (!stats_cb || !stats_cb->callback)
+ return TRUE;
+
+ switch (data_type) {
+ case WEBRTC_STATS_PROP_TYPE_BOOL:
+ prop_info.v_bool = *(bool *)result;
+ break;
+ case WEBRTC_STATS_PROP_TYPE_INT:
+ prop_info.v_int = *(int *)result;
+ break;
+ case WEBRTC_STATS_PROP_TYPE_INT64:
+ prop_info.v_int64 = *(int64_t *)result;
+ break;
+ case WEBRTC_STATS_PROP_TYPE_UINT:
+ prop_info.v_uint = *(unsigned int *)result;
+ break;
+ case WEBRTC_STATS_PROP_TYPE_UINT64:
+ prop_info.v_uint64 = *(uint64_t *)result;
+ break;
+ case WEBRTC_STATS_PROP_TYPE_FLOAT:
+ prop_info.v_float = *(float *)result;
+ break;
+ case WEBRTC_STATS_PROP_TYPE_DOUBLE:
+ prop_info.v_double = *(double *)result;
+ break;
+ case WEBRTC_STATS_PROP_TYPE_STRING:
+ prop_info.v_string = (const char *)result;
+ break;
+ default:
+ LOG_ERROR_IF_REACHED("data_type(%d)", data_type);
+ return TRUE;
+ }
+
+ 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;
+ }
+
+ return TRUE;
+}
+
static gboolean __stats_field_foreach_cb(GQuark field_id, const GValue *val, gpointer user_data)
{
stats_userdata_s *stats = (stats_userdata_s *)user_data;
+ const gchar *field_name = g_quark_to_string(field_id);
+ webrtc_stats_prop_e prop;
int i, j;
RET_VAL_IF(user_data == NULL, FALSE, "user_data is NULL");
/* Note that it only allow fields pre-defined in list */
for (i = 0; stats->fields_list[i]; i++)
for (j = 0; stats->fields_list[i][j].name; j++)
- if (stats->fields_list[i][j].id == field_id)
+ if (stats->fields_list[i][j].id == field_id) {
+ prop = stats->fields_list[i][j].prop;
goto invoke_cb;
+ }
/* field id below will be skipped here, it should be handled with gst_structure_foreach() */
- if (!g_strcmp0(g_quark_to_string(field_id), "gst-rtpjitterbuffer-stats") ||
- !g_strcmp0(g_quark_to_string(field_id), "gst-rtpsource-stats"))
+ if (!g_strcmp0(field_name, "gst-rtpjitterbuffer-stats") ||
+ !g_strcmp0(field_name, "gst-rtpsource-stats"))
return TRUE;
- LOG_WARNING("this field[%s] is not supported", g_quark_to_string(field_id));
+ LOG_WARNING("this field[%s] is not supported", field_name);
return TRUE;
invoke_cb:
- /* TODO: invoke callback */
switch (G_VALUE_TYPE(val)) {
- case G_TYPE_BOOLEAN:
- LOG_DEBUG("field_id[%s] GType[%s] value[%u]",
- g_quark_to_string(field_id), g_type_name(G_VALUE_TYPE(val)), g_value_get_boolean(val));
- break;
- case G_TYPE_INT:
- LOG_DEBUG("field_id[%s] GType[%s] value[%d]",
- g_quark_to_string(field_id), g_type_name(G_VALUE_TYPE(val)), g_value_get_int(val));
- break;
- case G_TYPE_INT64:
- LOG_DEBUG("field_id[%s] GType[%s] value[%"G_GINT64_FORMAT"]",
- g_quark_to_string(field_id), g_type_name(G_VALUE_TYPE(val)), g_value_get_int64(val));
- break;
- case G_TYPE_UINT:
- LOG_DEBUG("field_id[%s] GType[%s] value[%u]",
- g_quark_to_string(field_id), g_type_name(G_VALUE_TYPE(val)), g_value_get_uint(val));
- break;
- case G_TYPE_UINT64:
- LOG_DEBUG("field_id[%s] GType[%s] value[%"G_GUINT64_FORMAT"]",
- g_quark_to_string(field_id), g_type_name(G_VALUE_TYPE(val)), g_value_get_uint64(val));
- break;
- case G_TYPE_FLOAT:
- LOG_DEBUG("field_id[%s] GType[%s] value[%f]",
- g_quark_to_string(field_id), g_type_name(G_VALUE_TYPE(val)), g_value_get_float(val));
- break;
- case G_TYPE_DOUBLE:
- LOG_DEBUG("field_id[%s] GType[%s] value[%lf]",
- g_quark_to_string(field_id), g_type_name(G_VALUE_TYPE(val)), g_value_get_double(val));
- break;
- case G_TYPE_STRING:
- LOG_DEBUG("field_id[%s] GType[%s] value[%s]",
- g_quark_to_string(field_id), g_type_name(G_VALUE_TYPE(val)), g_value_get_string(val));
- break;
+ case G_TYPE_BOOLEAN: {
+ gboolean result = g_value_get_boolean(val);
+ LOG_DEBUG("field[%23s] GType[%18s] value[%21u]",
+ field_name, g_type_name(G_VALUE_TYPE(val)), result);
+
+ return __invoke_stats_cb(stats->type, field_name, prop, WEBRTC_STATS_PROP_TYPE_BOOL, &result, &stats->p_userdata->stats_cb);
+ }
+ case G_TYPE_INT: {
+ gint result = g_value_get_int(val);
+ LOG_DEBUG("field[%23s] GType[%18s] value[%21d]",
+ field_name, g_type_name(G_VALUE_TYPE(val)), result);
+
+ return __invoke_stats_cb(stats->type, field_name, prop, WEBRTC_STATS_PROP_TYPE_INT, &result, &stats->p_userdata->stats_cb);
+ }
+ case G_TYPE_INT64: {
+ gint64 result = g_value_get_int64(val);
+ LOG_DEBUG("field[%23s] GType[%18s] value[%21"G_GINT64_FORMAT"]",
+ field_name, g_type_name(G_VALUE_TYPE(val)), result);
+
+ return __invoke_stats_cb(stats->type, field_name, prop, WEBRTC_STATS_PROP_TYPE_INT64, &result, &stats->p_userdata->stats_cb);
+ }
+ case G_TYPE_UINT: {
+ guint result = g_value_get_uint(val);
+ LOG_DEBUG("field[%23s] GType[%18s] value[%21u]",
+ field_name, g_type_name(G_VALUE_TYPE(val)), result);
+
+ return __invoke_stats_cb(stats->type, field_name, prop, WEBRTC_STATS_PROP_TYPE_UINT, &result, &stats->p_userdata->stats_cb);
+ }
+ case G_TYPE_UINT64: {
+ guint64 result = g_value_get_uint64(val);
+ LOG_DEBUG("field[%23s] GType[%18s] value[%21"G_GUINT64_FORMAT"]",
+ field_name, g_type_name(G_VALUE_TYPE(val)), result);
+
+ return __invoke_stats_cb(stats->type, field_name, prop, WEBRTC_STATS_PROP_TYPE_UINT64, &result, &stats->p_userdata->stats_cb);
+ }
+ case G_TYPE_FLOAT: {
+ gfloat result = g_value_get_float(val);
+ LOG_DEBUG("field[%23s] GType[%18s] value[%21f]",
+ field_name, g_type_name(G_VALUE_TYPE(val)), result);
+
+ return __invoke_stats_cb(stats->type, field_name, prop, WEBRTC_STATS_PROP_TYPE_FLOAT, &result, &stats->p_userdata->stats_cb);
+ }
+ case G_TYPE_DOUBLE: {
+ gdouble result = g_value_get_double(val);
+ LOG_DEBUG("field[%23s] GType[%18s] value[%21lf]",
+ field_name, g_type_name(G_VALUE_TYPE(val)), result);
+
+ return __invoke_stats_cb(stats->type, field_name, prop, WEBRTC_STATS_PROP_TYPE_DOUBLE, &result, &stats->p_userdata->stats_cb);
+ }
+ case G_TYPE_STRING: {
+ const gchar *result = g_value_get_string(val);
+ LOG_DEBUG("field[%23s] GType[%18s] value[%21s]",
+ field_name, g_type_name(G_VALUE_TYPE(val)), result);
+
+ return __invoke_stats_cb(stats->type, field_name, prop, WEBRTC_STATS_PROP_TYPE_STRING, (void *)result, &stats->p_userdata->stats_cb);
+ }
default:
if (!g_strcmp0(g_type_name(G_VALUE_TYPE(val)), "GstWebRTCStatsType")) {
- LOG_DEBUG("field_id[%s] GType[%s] value[%d]",
- g_quark_to_string(field_id), g_type_name(G_VALUE_TYPE(val)), g_value_get_enum(val));
+ LOG_DEBUG("field[%23s] GType[%18s] value[%21d]", field_name, g_type_name(G_VALUE_TYPE(val)), g_value_get_enum(val));
break;
}
- LOG_ERROR("invalid type, field_id[%s] GType[%s]",
- g_quark_to_string(field_id), g_type_name(G_VALUE_TYPE(val)));
+ LOG_ERROR("invalid type, field[%23s] GType[%18s]", field_name, g_type_name(G_VALUE_TYPE(val)));
break;
}
return TRUE;
}
-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)
+static void __stats_codec_invoke_callback(const GstStructure *s, webrtc_stats_type_e type, 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 };
+ stats_userdata_s stats_userdata = { .p_userdata = user_data, .type = type, .fields_list = fields_list };
RET_IF(user_data == NULL, "user_data is NULL");
gst_structure_foreach(s, __stats_field_foreach_cb, &stats_userdata);
}
-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)
+static void __stats_inbound_rtp_invoke_callback(const GstStructure *s, webrtc_stats_type_e type, 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 };
+ stats_userdata_s stats_userdata = { .p_userdata = user_data, .type = type, .fields_list = fields_list };
GstStructure *rtpjitterbuffer_stats;
GstStructure *rtpsource_stats;
gst_structure_foreach(rtpsource_stats, __stats_field_foreach_cb, &stats_userdata);
}
-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)
+static void __stats_outbound_rtp_invoke_callback(const GstStructure *s, webrtc_stats_type_e type, 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 };
+ stats_userdata_s stats_userdata = { .p_userdata = user_data, .type = type, .fields_list = fields_list };
GstStructure *rtpsource_stats;
RET_IF(user_data == NULL, "user_data is NULL");
gst_structure_foreach(rtpsource_stats, __stats_field_foreach_cb, &stats_userdata);
}
-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)
+static void __stats_remote_inbound_rtp_invoke_callback(const GstStructure *s, webrtc_stats_type_e type, 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 };
+ stats_userdata_s stats_userdata = { .p_userdata = user_data, .type = type, .fields_list = fields_list };
RET_IF(user_data == NULL, "user_data is NULL");
LOG_DEBUG_ENTER();
gst_structure_foreach(s, __stats_field_foreach_cb, &stats_userdata);
}
-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)
+static void __stats_remote_outbound_rtp_invoke_callback(const GstStructure *s, webrtc_stats_type_e type, 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 };
+ stats_userdata_s stats_userdata = { .p_userdata = user_data, .type = type, .fields_list = fields_list };
RET_IF(user_data == NULL, "user_data is NULL");
LOG_DEBUG_ENTER();
gst_structure_foreach(s, __stats_field_foreach_cb, &stats_userdata);
}
-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)
+static void __stats_csrc_invoke_callback(const GstStructure *s, webrtc_stats_type_e type, 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 };
+ stats_userdata_s stats_userdata = { .p_userdata = user_data, .type = type, .fields_list = fields_list };
RET_IF(user_data == NULL, "user_data is NULL");
LOG_DEBUG_ENTER();
/* not implemented */
}
-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)
+static void __stats_peer_connection_invoke_callback(const GstStructure *s, webrtc_stats_type_e type, 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 };
+ stats_userdata_s stats_userdata = { .p_userdata = user_data, .type = type, .fields_list = fields_list };
RET_IF(user_data == NULL, "user_data is NULL");
LOG_DEBUG_ENTER();
gst_structure_foreach(s, __stats_field_foreach_cb, &stats_userdata);
}
-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)
+static void __stats_data_channel_invoke_callback(const GstStructure *s, webrtc_stats_type_e type, 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 };
+ stats_userdata_s stats_userdata = { .p_userdata = user_data, .type = type, .fields_list = fields_list };
RET_IF(user_data == NULL, "user_data is NULL");
LOG_DEBUG_ENTER();
/* not implemented */
}
-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)
+static void __stats_stream_invoke_callback(const GstStructure *s, webrtc_stats_type_e type, 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 };
+ stats_userdata_s stats_userdata = { .p_userdata = user_data, .type = type, .fields_list = fields_list };
RET_IF(user_data == NULL, "user_data is NULL");
LOG_DEBUG_ENTER();
/* not implemented */
}
-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)
+static void __stats_transport_invoke_callback(const GstStructure *s, webrtc_stats_type_e type, 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 };
+ stats_userdata_s stats_userdata = { .p_userdata = user_data, .type = type, .fields_list = fields_list };
RET_IF(user_data == NULL, "user_data is NULL");
LOG_DEBUG_ENTER();
gst_structure_foreach(s, __stats_field_foreach_cb, &stats_userdata);
}
-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)
+static void __stats_candidate_pair_invoke_callback(const GstStructure *s, webrtc_stats_type_e type, 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 };
+ stats_userdata_s stats_userdata = { .p_userdata = user_data, .type = type, .fields_list = fields_list };
RET_IF(user_data == NULL, "user_data is NULL");
LOG_DEBUG_ENTER();
/* not implemented */
}
-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)
+static void __stats_local_candidate_invoke_callback(const GstStructure *s, webrtc_stats_type_e type, 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 };
+ stats_userdata_s stats_userdata = { .p_userdata = user_data, .type = type, .fields_list = fields_list };
RET_IF(user_data == NULL, "user_data is NULL");
LOG_DEBUG_ENTER();
/* not implemented */
}
-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)
+static void __stats_remote_candidate_invoke_callback(const GstStructure *s, webrtc_stats_type_e type, 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 };
+ stats_userdata_s stats_userdata = { .p_userdata = user_data, .type = type, .fields_list = fields_list };
RET_IF(user_data == NULL, "user_data is NULL");
LOG_DEBUG_ENTER();
/* not implemented */
}
-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)
+static void __stats_certificate_invoke_callback(const GstStructure *s, webrtc_stats_type_e type, 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 };
+ stats_userdata_s stats_userdata = { .p_userdata = user_data, .type = type, .fields_list = fields_list };
RET_IF(user_data == NULL, "user_data is NULL");
LOG_DEBUG_ENTER();
/* not implemented */
}
-typedef void (*stats_func)(const GstStructure *s, stats_type_mask_e type_mask, stats_field_s **fields_list, promise_userdata_s *user_data);
+typedef void (*stats_func)(const GstStructure *s, webrtc_stats_type_e type, stats_field_s **fields_list, promise_userdata_s *user_data);
typedef struct {
stats_func func;
- stats_type_mask_e type_mask;
+ int type_mask;
stats_field_s **fields_list;
} parse_stats_s;
+/* Definitions below are not exported types due to the incompletion. */
+#define WEBRTC_STATS_TYPE_INBOUND_RTP 0x0002 /**< Inbound RTP */
+#define WEBRTC_STATS_TYPE_OUTBOUND_RTP 0x0004 /**< Outbound RTP */
+#define WEBRTC_STATS_TYPE_REMOTE_INBOUND_RTP 0x0008 /**< Remote Inbound RTP */
+#define WEBRTC_STATS_TYPE_REMOTE_OUTBOUND_RTP 0x000F /**< Remote Outbound RTP */
+#define WEBRTC_STATS_TYPE_PEER_CONNECTION 0x0010 /**< Peer Connection */
+#define WEBRTC_STATS_TYPE_CSRC 0x0020 /**< CSRC */
+#define WEBRTC_STATS_TYPE_DATA_CHANNEL 0x0040 /**< Data Channel */
+#define WEBRTC_STATS_TYPE_STREAM 0x0080 /**< Stream */
+#define WEBRTC_STATS_TYPE_TRANSPORT 0x00F0 /**< Transport */
+#define WEBRTC_STATS_TYPE_CANDIDATE_PAIR 0x0100 /**< Candidate Pair */
+#define WEBRTC_STATS_TYPE_LOCAL_CANDIDATE 0x0200 /**< Local Candidate */
+#define WEBRTC_STATS_TYPE_REMOTE_CANDIDATE 0x0400 /**< Remote Candidate */
+#define WEBRTC_STATS_TYPE_CERTIFICATE 0x0800 /**< Certificate */
+
+/* Refer to GstWebRTCStatsType of webrtc_fwd.h */
static parse_stats_s parse_stats[] = {
[GST_WEBRTC_STATS_CODEC] = {
- __stats_codec_invoke_callback, STATS_TYPE_CODEC_MASK, __stats_codec_fields_list },
+ __stats_codec_invoke_callback, WEBRTC_STATS_TYPE_CODEC, __stats_codec_fields_list },
[GST_WEBRTC_STATS_INBOUND_RTP] = {
- __stats_inbound_rtp_invoke_callback, STATS_TYPE_INBOUND_RTP_MASK, __stats_inbound_rtp_fields_list },
+ __stats_inbound_rtp_invoke_callback, WEBRTC_STATS_TYPE_INBOUND_RTP, __stats_inbound_rtp_fields_list },
[GST_WEBRTC_STATS_OUTBOUND_RTP] = {
- __stats_outbound_rtp_invoke_callback, STATS_TYPE_OUTBOUND_RTP_MASK, __stats_outbound_rtp_fields_list },
+ __stats_outbound_rtp_invoke_callback, WEBRTC_STATS_TYPE_OUTBOUND_RTP, __stats_outbound_rtp_fields_list },
[GST_WEBRTC_STATS_REMOTE_INBOUND_RTP] = {
- __stats_remote_inbound_rtp_invoke_callback, STATS_TYPE_REMOTE_INBOUND_RTP_MASK, __stats_remote_inbound_rtp_fields_list },
+ __stats_remote_inbound_rtp_invoke_callback, WEBRTC_STATS_TYPE_REMOTE_INBOUND_RTP, __stats_remote_inbound_rtp_fields_list },
[GST_WEBRTC_STATS_REMOTE_OUTBOUND_RTP] = {
- __stats_remote_outbound_rtp_invoke_callback, STATS_TYPE_REMOTE_OUTBOUND_RTP_MASK, __stats_remote_outbound_rtp_fields_list },
+ __stats_remote_outbound_rtp_invoke_callback, WEBRTC_STATS_TYPE_REMOTE_OUTBOUND_RTP, __stats_remote_outbound_rtp_fields_list },
[GST_WEBRTC_STATS_CSRC] = {
- __stats_csrc_invoke_callback, STATS_TYPE_CSRC_MASK, NULL },
+ __stats_csrc_invoke_callback, WEBRTC_STATS_TYPE_CSRC, NULL },
[GST_WEBRTC_STATS_PEER_CONNECTION] = {
- __stats_peer_connection_invoke_callback, STATS_TYPE_PEER_CONNECTION_MASK, __stats_peer_connection_fields_list },
+ __stats_peer_connection_invoke_callback, WEBRTC_STATS_TYPE_PEER_CONNECTION, __stats_peer_connection_fields_list },
[GST_WEBRTC_STATS_DATA_CHANNEL] = {
- __stats_data_channel_invoke_callback, STATS_TYPE_DATA_CHANNEL_MASK, NULL },
+ __stats_data_channel_invoke_callback, WEBRTC_STATS_TYPE_DATA_CHANNEL, NULL },
[GST_WEBRTC_STATS_STREAM] = {
- __stats_stream_invoke_callback, STATS_TYPE_STREAM_MASK, NULL },
+ __stats_stream_invoke_callback, WEBRTC_STATS_TYPE_STREAM, NULL },
[GST_WEBRTC_STATS_TRANSPORT] = {
- __stats_transport_invoke_callback, STATS_TYPE_TRANSPORT_MASK, __stats_transport_fields_list },
+ __stats_transport_invoke_callback, WEBRTC_STATS_TYPE_TRANSPORT, __stats_transport_fields_list },
[GST_WEBRTC_STATS_CANDIDATE_PAIR] = {
- __stats_candidate_pair_invoke_callback, STATS_TYPE_CANDIDATE_PAIR_MASK, NULL },
+ __stats_candidate_pair_invoke_callback, WEBRTC_STATS_TYPE_CANDIDATE_PAIR, NULL },
[GST_WEBRTC_STATS_LOCAL_CANDIDATE] = {
- __stats_local_candidate_invoke_callback, STATS_TYPE_LOCAL_CANDIDATE_MASK, NULL },
+ __stats_local_candidate_invoke_callback, WEBRTC_STATS_TYPE_LOCAL_CANDIDATE, NULL },
[GST_WEBRTC_STATS_REMOTE_CANDIDATE] = {
- __stats_remote_candidate_invoke_callback, STATS_TYPE_REMOTE_CANDIDATE_MASK, NULL },
+ __stats_remote_candidate_invoke_callback, WEBRTC_STATS_TYPE_REMOTE_CANDIDATE, NULL },
[GST_WEBRTC_STATS_CERTIFICATE] = {
- __stats_certificate_invoke_callback, STATS_TYPE_CERTIFICATE_MASK, NULL }
+ __stats_certificate_invoke_callback, WEBRTC_STATS_TYPE_CERTIFICATE, NULL }
};
static gboolean __webrtcbin_stats_cb(GQuark field_id, const GValue *value, gpointer user_data)
webrtc_s *webrtc = (webrtc_s *)user_data;
if (webrtc->state == WEBRTC_STATE_PLAYING)
- _webrtcbin_get_stats(webrtc, STATS_TYPE_ALL_MASK, NULL, NULL);
+ _webrtcbin_get_stats(webrtc, WEBRTC_STATS_TYPE_GST_ALL, NULL, NULL);
return G_SOURCE_CONTINUE;
}