From: Sangchul Lee Date: Wed, 16 Mar 2022 04:13:43 +0000 (+0900) Subject: Add statistics API X-Git-Tag: submit/tizen/20220331.093038~9 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=refs%2Fchanges%2F77%2F272177%2F13;p=platform%2Fcore%2Fapi%2Fwebrtc.git Add statistics API For now, only 'codec' statistics type is exported. Other types will be supported with the following patches. Function is added to get all the properties per statistics type. - webrtc_foreach_stats() Callback function prototype is added as below. - typedef bool (*webrtc_stats_cb)(webrtc_stats_type_e type, webrtc_stats_prop_info_s *prop_info, void *user_data); Enum is added as below for statistics type. - WEBRTC_STATS_TYPE_CODEC Struct is added to be used as a parameter of the callback function. - webrtc_stats_prop_info_s Enums are added as below for statisics property - WEBRTC_STATS_PROP_TIMESTAMP - WEBRTC_STATS_PROP_ID - WEBRTC_STATS_PROP_PAYLOAD_TYPE - WEBRTC_STATS_PROP_CLOCK_RATE - WEBRTC_STATS_PROP_CHANNELS - WEBRTC_STATS_PROP_MIME_TYPE - WEBRTC_STATS_PROP_CODEC_TYPE - WEBRTC_STATS_PROP_SDP_FMTP_LINE Enums are added as below for statistics property data type - WEBRTC_STATS_PROP_TYPE_BOOL - WEBRTC_STATS_PROP_TYPE_INT - WEBRTC_STATS_PROP_TYPE_UINT - WEBRTC_STATS_PROP_TYPE_INT64 - WEBRTC_STATS_PROP_TYPE_UINT64 - WEBRTC_STATS_PROP_TYPE_FLOAT - WEBRTC_STATS_PROP_TYPE_DOUBLE - WEBRTC_STATS_PROP_TYPE_STRING [Version] 0.3.69 [Issue Type] API Change-Id: I52bbe25d6c03c4db1b0e0ffbf7c8f293da0b62a0 Signed-off-by: Sangchul Lee --- diff --git a/include/webrtc.h b/include/webrtc.h index 19f4c0ba..852d0ce4 100644 --- a/include/webrtc.h +++ b/include/webrtc.h @@ -264,6 +264,97 @@ typedef enum { 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; + /** * @} */ @@ -587,6 +678,61 @@ typedef void (*webrtc_data_channel_close_cb)(webrtc_data_channel_h channel, void * @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); + /** * @} */ @@ -2363,6 +2509,33 @@ int webrtc_data_channel_get_buffered_amount_low_threshold(webrtc_data_channel_h */ 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); + /** * @} */ diff --git a/packaging/capi-media-webrtc.spec b/packaging/capi-media-webrtc.spec index 0776d2e7..ea544869 100644 --- a/packaging/capi-media-webrtc.spec +++ b/packaging/capi-media-webrtc.spec @@ -1,6 +1,6 @@ Name: capi-media-webrtc Summary: A WebRTC library in Tizen Native API -Version: 0.3.68 +Version: 0.3.69 Release: 0 Group: Multimedia/API License: Apache-2.0 diff --git a/src/webrtc.c b/src/webrtc.c index 986a6aaa..e4eb7305 100644 --- a/src/webrtc.c +++ b/src/webrtc.c @@ -2023,3 +2023,22 @@ int webrtc_data_channel_unset_buffered_amount_low_cb(webrtc_data_channel_h chann return WEBRTC_ERROR_NONE; } + +int webrtc_foreach_stats(webrtc_h webrtc, int type_mask, webrtc_stats_cb callback, void *user_data) +{ + g_autoptr(GMutexLocker) locker = NULL; + webrtc_s *_webrtc = (webrtc_s *)webrtc; + + RET_VAL_IF(_webrtc == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "webrtc is NULL"); + RET_VAL_IF(callback == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "callback is NULL"); + + locker = g_mutex_locker_new(&_webrtc->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); + + LOG_INFO("webrtc[%p] type_mask[0x%x] callback[%p] user_data[%p]", webrtc, type_mask, callback, user_data); + + return WEBRTC_ERROR_NONE; +} diff --git a/src/webrtc_stats.c b/src/webrtc_stats.c index 271e8636..1af0128c 100644 --- a/src/webrtc_stats.c +++ b/src/webrtc_stats.c @@ -18,9 +18,11 @@ #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; @@ -34,10 +36,10 @@ typedef struct _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 } }; /* @@ -53,14 +55,14 @@ static stats_field_s __stats_common_fields[] = { * "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 } }; /* @@ -75,13 +77,13 @@ static stats_field_s __stats_codec_fields[] = { * "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 } }; /* @@ -94,12 +96,12 @@ static stats_field_s __stats_rtp_stream_fields[] = { * "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 } }; /* @@ -109,13 +111,13 @@ static stats_field_s __stats_received_rtp_stream_fields[] = { * "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 } }; /* @@ -126,9 +128,9 @@ static stats_field_s __stats_inbound_rtp_stream_fields[] = { * "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 } }; /* @@ -138,8 +140,8 @@ static stats_field_s __stats_sent_rtp_stream_fields[] = { * "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 } }; /* @@ -151,10 +153,10 @@ static stats_field_s __stats_outbound_rtp_stream_fields[] = { * "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 } }; /* @@ -165,9 +167,9 @@ static stats_field_s __stats_remote_inbound_rtp_stream_fields[] = { * "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 } }; /* @@ -180,16 +182,16 @@ static stats_field_s __stats_remote_outbound_rtp_stream_fields[] = { * "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[] = { @@ -256,25 +258,6 @@ static stats_field_s *__stats_transport_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; @@ -283,13 +266,60 @@ typedef struct _promise_userdata_s { 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"); @@ -300,69 +330,92 @@ static gboolean __stats_field_foreach_cb(GQuark field_id, const GValue *val, gpo /* 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"); @@ -371,9 +424,9 @@ static void __stats_codec_invoke_callback(const GstStructure *s, stats_type_mask 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; @@ -393,9 +446,9 @@ static void __stats_inbound_rtp_invoke_callback(const GstStructure *s, stats_typ 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"); @@ -409,9 +462,9 @@ static void __stats_outbound_rtp_invoke_callback(const GstStructure *s, stats_ty 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(); @@ -420,9 +473,9 @@ static void __stats_remote_inbound_rtp_invoke_callback(const GstStructure *s, st 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(); @@ -430,9 +483,9 @@ static void __stats_remote_outbound_rtp_invoke_callback(const GstStructure *s, s 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(); @@ -441,9 +494,9 @@ static void __stats_csrc_invoke_callback(const GstStructure *s, stats_type_mask_ /* 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(); @@ -451,9 +504,9 @@ static void __stats_peer_connection_invoke_callback(const GstStructure *s, stats 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(); @@ -462,9 +515,9 @@ static void __stats_data_channel_invoke_callback(const GstStructure *s, stats_ty /* 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(); @@ -473,9 +526,9 @@ static void __stats_stream_invoke_callback(const GstStructure *s, stats_type_mas /* 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(); @@ -483,9 +536,9 @@ static void __stats_transport_invoke_callback(const GstStructure *s, stats_type_ 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(); @@ -494,9 +547,9 @@ static void __stats_candidate_pair_invoke_callback(const GstStructure *s, stats_ /* 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(); @@ -505,9 +558,9 @@ static void __stats_local_candidate_invoke_callback(const GstStructure *s, stats /* 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(); @@ -516,9 +569,9 @@ static void __stats_remote_candidate_invoke_callback(const GstStructure *s, stat /* 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(); @@ -527,43 +580,59 @@ static void __stats_certificate_invoke_callback(const GstStructure *s, stats_typ /* 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) @@ -638,7 +707,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, STATS_TYPE_ALL_MASK, NULL, NULL); + _webrtcbin_get_stats(webrtc, WEBRTC_STATS_TYPE_GST_ALL, NULL, NULL); return G_SOURCE_CONTINUE; } diff --git a/test/webrtc_test.c b/test/webrtc_test.c index 3ba5a59a..f4afb476 100644 --- a/test/webrtc_test.c +++ b/test/webrtc_test.c @@ -1830,6 +1830,61 @@ static void _webrtc_data_channel_get_buffered_amount(int index) } } +static 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: + g_print("stats type[0x%04x], prop[%23s, 0x%08x, type:%d, value:%21d], user_data[%p]\n", + type, prop_info->name, prop_info->prop, prop_info->type, prop_info->v_bool, user_data); + break; + case WEBRTC_STATS_PROP_TYPE_INT: + g_print("stats type[0x%04x], prop[%23s, 0x%08x, type:%d, value:%21d], user_data[%p]\n", + type, prop_info->name, prop_info->prop, prop_info->type, prop_info->v_int, user_data); + break; + case WEBRTC_STATS_PROP_TYPE_INT64: + g_print("stats type[0x%04x], prop[%23s, 0x%08x, type:%d, value:%21"PRId64"], user_data[%p]\n", + type, prop_info->name, prop_info->prop, prop_info->type, prop_info->v_int64, user_data); + break; + case WEBRTC_STATS_PROP_TYPE_UINT: + g_print("stats type[0x%04x], prop[%23s, 0x%08x, type:%d, value:%21u], user_data[%p]\n", + type, prop_info->name, prop_info->prop, prop_info->type, prop_info->v_uint, user_data); + break; + case WEBRTC_STATS_PROP_TYPE_UINT64: + g_print("stats type[0x%04x], prop[%23s, 0x%08x, type:%d, value:%21"PRIu64"], user_data[%p]\n", + type, prop_info->name, prop_info->prop, prop_info->type, prop_info->v_uint64, user_data); + break; + case WEBRTC_STATS_PROP_TYPE_FLOAT: + g_print("stats type[0x%04x], prop[%23s, 0x%08x, type:%d, value:%21f], user_data[%p]\n", + type, prop_info->name, prop_info->prop, prop_info->type, prop_info->v_float, user_data); + break; + case WEBRTC_STATS_PROP_TYPE_DOUBLE: + g_print("stats type[0x%04x], prop[%23s, 0x%08x, type:%d, value:%21lf], user_data[%p]\n", + type, prop_info->name, prop_info->prop, prop_info->type, prop_info->v_double, user_data); + break; + case WEBRTC_STATS_PROP_TYPE_STRING: + g_print("stats type[0x%04x], prop[%23s, 0x%08x, type:%d, value:%21s], user_data[%p]\n", + type, prop_info->name, prop_info->prop, prop_info->type, prop_info->v_string, user_data); + break; + default: + g_printerr("invalid prop_info->type, stats type[0x%04x], prop[%23s, 0x%08x, type:%d], user_data[%p]\n", + type, prop_info->name, prop_info->prop, prop_info->type, user_data); + break; + } + + return true; +} + +static void _webrtc_foreach_stats(int index) +{ + int ret = WEBRTC_ERROR_NONE; + + ret = webrtc_foreach_stats(g_conns[index].webrtc, WEBRTC_STATS_TYPE_ALL, __stats_cb, NULL); + if (ret != WEBRTC_ERROR_NONE) + g_print("failed to webrtc_foreach_stats(), index[%d]\n", index); + else + g_print("webrtc_foreach_stats() success, index[%d]\n", index); +} + static void __error_cb(webrtc_h webrtc, webrtc_error_e error, webrtc_state_e state, void *user_data) { g_print("__error_cb() is invoked, webrtc[%p], error[0x%x], state[%d], user_data[%p]\n", @@ -4467,6 +4522,9 @@ void _interpret_main_menu(char *cmd) } else if (strncmp(cmd, "ubc", 3) == 0) { _webrtc_data_channel_unset_buffered_amount_low_cb(0); + } else if (strncmp(cmd, "sts", 3) == 0) { + _webrtc_foreach_stats(0); + } else { g_print("unknown menu \n"); } @@ -4578,6 +4636,8 @@ void display_sub_basic() g_print("sbc. Set buffered amount low callback\t"); g_print("ubc. Unset buffered amount low callback\n"); g_print("gbt. Get buffered amount low threshold\n"); + g_print("------------------------------------- Stats ---------------------------------------------\n"); + g_print("sts. Get stats\n"); g_print("------------------------------------- Callbacks -----------------------------------------\n"); g_print("sac. Set all callbacks below (except for the encoded frame callbacks)\n"); g_print("san. Set all the negotiation state change callbacks\t");