diff --git a/girs/GstWebRTC-1.0.gir b/girs/GstWebRTC-1.0.gir
index 76a9410d9a..acf46f8dc7 100644
--- a/girs/GstWebRTC-1.0.gir
+++ b/girs/GstWebRTC-1.0.gir
@@ -190,6 +190,97 @@ and/or use gtk-doc annotations. -->
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -1482,37 +1573,67 @@ stops automatic ICE gathering.
-
+
+ The network port number used by the candidate (Since: 1.22)
+ A string that uniquely identifies the object that is being
+ monitored to produce this set of statistics (Since: 1.22)
+ The candidate type (Since: 1.22)
+ A string specifying the protocol (tcp or udp) used to transmit data
+on the @port (Since: 1.22)
+ The candidate's priority, corresponding to RTCIceCandidate.priority (Since: 1.22)
+ For local candidates, the url property is the URL of the ICE server
+from which the candidate was received (Since: 1.22)
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/subprojects/gst-plugins-bad/ext/webrtc/gstwebrtcbin.c b/subprojects/gst-plugins-bad/ext/webrtc/gstwebrtcbin.c
index d781204fe7..7f806f6b4a 100644
--- a/subprojects/gst-plugins-bad/ext/webrtc/gstwebrtcbin.c
+++ b/subprojects/gst-plugins-bad/ext/webrtc/gstwebrtcbin.c
@@ -9256,6 +9256,11 @@ gst_webrtc_bin_class_init (GstWebRTCBinClass * klass)
* "protocol" G_TYPE_STRING Either "udp" or "tcp". Based on the "transport" defined in RFC 5245
* "relay-protocol" G_TYPE_STRING protocol used by the endpoint to communicate with the TURN server. Only present for local candidates. Either "udp", "tcp" or "tls"
* "url" G_TYPE_STRING URL of the ICE server from which the candidate was obtained. Only present for local candidates
+ * "foundation" G_TYPE_STRING ICE foundation as defined in RFC 5245 section 15.1 (Since: 1.28)
+ * "related-address" G_TYPE_STRING ICE rel-addr as defined in RFC 5245 section 15.1. Only set for server-reflexive, peer-reflexive and relay candidates (Since: 1.28)
+ * "related-port" G_TYPE_UINT ICE rel-port as defined in RFC 5245 section 15.1. Only set for serverreflexive, peer-reflexive and relay candidates (Since: 1.28)
+ * "username-fragment" G_TYPE_STRING ICE username fragment as defined in RFC 5245 section 7.1.2.3 (Since: 1.28)
+ * "tcp-type" G_TYPE_STRING ICE candidate TCP type as defined in RTCIceTcpCandidateType (Since: 1.28)
*
* RTCIceCandidatePairStats supported fields (https://www.w3.org/TR/webrtc-stats/#candidatepair-dict*) (Since: 1.22)
*
diff --git a/subprojects/gst-plugins-bad/ext/webrtc/gstwebrtcstats.c b/subprojects/gst-plugins-bad/ext/webrtc/gstwebrtcstats.c
index a6ecec0357..3fce94863c 100644
--- a/subprojects/gst-plugins-bad/ext/webrtc/gstwebrtcstats.c
+++ b/subprojects/gst-plugins-bad/ext/webrtc/gstwebrtcstats.c
@@ -615,6 +615,11 @@ _get_stats_from_ice_candidates (GstWebRTCBin * webrtc,
long priority;
DOMString url;
DOMString relayProtocol;
+ DOMString foundation;
+ DOMString relatedAddress;
+ long relatedPort;
+ DOMString usernameFragment;
+ RTCIceTcpCandidateType tcpType;
*/
if (transport_id)
@@ -630,6 +635,21 @@ _get_stats_from_ice_candidates (GstWebRTCBin * webrtc,
NULL);
if (can->url)
gst_structure_set (stats, "url", G_TYPE_STRING, can->url, NULL);
+ if (can->ABI.abi.foundation)
+ gst_structure_set (stats, "foundation", G_TYPE_STRING,
+ can->ABI.abi.foundation, NULL);
+ if (can->ABI.abi.related_address)
+ gst_structure_set (stats, "related-address", G_TYPE_STRING,
+ can->ABI.abi.related_address, NULL);
+ if (can->ABI.abi.related_port)
+ gst_structure_set (stats, "related-port", G_TYPE_UINT,
+ can->ABI.abi.related_port, NULL);
+ if (can->ABI.abi.username_fragment)
+ gst_structure_set (stats, "username-fragment", G_TYPE_STRING,
+ can->ABI.abi.username_fragment, NULL);
+ if (can->ABI.abi.tcp_type)
+ gst_structure_set (stats, "tcp-type", G_TYPE_STRING, can->ABI.abi.tcp_type,
+ NULL);
gst_structure_set (s, id, GST_TYPE_STRUCTURE, stats, NULL);
gst_structure_free (stats);
diff --git a/subprojects/gst-plugins-bad/gst-libs/gst/webrtc/ice.c b/subprojects/gst-plugins-bad/gst-libs/gst/webrtc/ice.c
index f35652a27f..fc62cb9bb8 100644
--- a/subprojects/gst-plugins-bad/gst-libs/gst/webrtc/ice.c
+++ b/subprojects/gst-plugins-bad/gst-libs/gst/webrtc/ice.c
@@ -341,6 +341,9 @@ gst_webrtc_ice_candidate_stats_free (GstWebRTCICECandidateStats * stats)
if (stats) {
g_free (stats->ipaddr);
g_free (stats->url);
+ g_free (stats->ABI.abi.foundation);
+ g_free (stats->ABI.abi.related_address);
+ g_free (stats->ABI.abi.username_fragment);
}
g_free (stats);
@@ -364,6 +367,9 @@ gst_webrtc_ice_candidate_stats_copy (GstWebRTCICECandidateStats * stats)
copy->ipaddr = g_strdup (stats->ipaddr);
copy->url = g_strdup (stats->url);
+ copy->ABI.abi.foundation = g_strdup (stats->ABI.abi.foundation);
+ copy->ABI.abi.related_address = g_strdup (stats->ABI.abi.related_address);
+ copy->ABI.abi.username_fragment = g_strdup (stats->ABI.abi.username_fragment);
return copy;
}
diff --git a/subprojects/gst-plugins-bad/gst-libs/gst/webrtc/ice.h b/subprojects/gst-plugins-bad/gst-libs/gst/webrtc/ice.h
index e1422f37a2..32e21fbc62 100644
--- a/subprojects/gst-plugins-bad/gst-libs/gst/webrtc/ice.h
+++ b/subprojects/gst-plugins-bad/gst-libs/gst/webrtc/ice.h
@@ -47,6 +47,30 @@ struct _GstWebRTCICE
gpointer _gst_reserved[GST_PADDING];
};
+/**
+ * GstWebRTCICECandidateStats:
+ * @ipadd: A string containing the address of the candidate. This value may be
+ * an IPv4 address, an IPv6 address, or a fully-qualified domain name (Since: 1.22)
+ * @port: The network port number used by the candidate (Since: 1.22)
+ * @stream_id: A string that uniquely identifies the object that is being
+ * monitored to produce this set of statistics (Since: 1.22)
+ * @type: The candidate type (Since: 1.22)
+ * @proto: A string specifying the protocol (tcp or udp) used to transmit data
+ * on the @port (Since: 1.22)
+ * @replay_proto: A string identifying the protocol used by the endpoint for
+ * communicating with the TURN server; valid values are tcp, udp, and tls (Since: 1.22)
+ * @prio: The candidate's priority, corresponding to RTCIceCandidate.priority (Since: 1.22)
+ * @url: For local candidates, the url property is the URL of the ICE server
+ * from which the candidate was received (Since: 1.22)
+ * @foundation: The ICE foundation as defined in RFC5245 section 15.1 (Since: 1.28)
+ * @related_address: The ICE rel-addr defined in RFC5245 section 15.1 Only
+ * set for serverreflexive, peerreflexive and relay candidates. (Since: 1.28)
+ * @related_port: The ICE rel-addr defined in RFC5245 section 15.1. Only set
+ * for serverreflexive, peerreflexive and relay candidates. (Since: 1.28)
+ * @username_fragment: The ICE username fragment as defined in RFC5245 section 7.1.2.3 (Since: 1.28)
+ * @tcp_type: The ICE candidate TCP type, (Since: 1.28)
+ *
+ */
struct _GstWebRTCICECandidateStats
{
gchar *ipaddr;
@@ -58,9 +82,99 @@ struct _GstWebRTCICECandidateStats
guint prio;
gchar *url;
- gpointer _gst_reserved[GST_PADDING_LARGE];
+ union {
+ struct {
+ gchar *foundation;
+ gchar *related_address;
+ guint related_port;
+ gchar *username_fragment;
+ const gchar *tcp_type;
+ } abi;
+ /*< private >*/
+ gpointer _gst_reserved[GST_PADDING_LARGE];
+ } ABI;
};
+/**
+ * GST_WEBRTC_ICE_CANDIDATE_STATS_ADDRESS:
+ *
+ * Since: 1.28
+ */
+#define GST_WEBRTC_ICE_CANDIDATE_STATS_ADDRESS(c) ((c)->ipaddr)
+/**
+ * GST_WEBRTC_ICE_CANDIDATE_STATS_PORT:
+ *
+ * Since: 1.28
+ */
+#define GST_WEBRTC_ICE_CANDIDATE_STATS_PORT(c) ((c)->port)
+/**
+ * GST_WEBRTC_ICE_CANDIDATE_STATS_STREAM_ID:
+ *
+ * Since: 1.28
+ */
+#define GST_WEBRTC_ICE_CANDIDATE_STATS_STREAM_ID(c) ((c)->stream_id)
+/**
+ * GST_WEBRTC_ICE_CANDIDATE_STATS_TYPE:
+ *
+ * Since: 1.28
+ */
+#define GST_WEBRTC_ICE_CANDIDATE_STATS_TYPE(c) ((c)->type)
+/**
+ * GST_WEBRTC_ICE_CANDIDATE_STATS_PROTOCOL:
+ *
+ * Since: 1.28
+ */
+#define GST_WEBRTC_ICE_CANDIDATE_STATS_PROTOCOL(c) ((c)->proto)
+/**
+ * GST_WEBRTC_ICE_CANDIDATE_STATS_RELAY_PROTOCOL:
+ *
+ * Since: 1.28
+ */
+#define GST_WEBRTC_ICE_CANDIDATE_STATS_RELAY_PROTOCOL(c) ((c)->relay_proto)
+/**
+ * GST_WEBRTC_ICE_CANDIDATE_STATS_PRIORITY:
+ *
+ * Since: 1.28
+ */
+#define GST_WEBRTC_ICE_CANDIDATE_STATS_PRIORITY(c) ((c)->prio)
+/**
+ * GST_WEBRTC_ICE_CANDIDATE_STATS_URL:
+ *
+ * Since: 1.28
+ */
+#define GST_WEBRTC_ICE_CANDIDATE_STATS_URL(c) ((c)->url)
+
+/**
+ * GST_WEBRTC_ICE_CANDIDATE_STATS_FOUNDATION:
+ *
+ * Since: 1.28
+ */
+#define GST_WEBRTC_ICE_CANDIDATE_STATS_FOUNDATION(c) ((c)->ABI.abi.foundation)
+/**
+ * GST_WEBRTC_ICE_CANDIDATE_STATS_RELATED_ADDRESS:
+ *
+ * Since: 1.28
+ */
+#define GST_WEBRTC_ICE_CANDIDATE_STATS_RELATED_ADDRESS(c) ((c)->ABI.abi.related_address)
+/**
+ * GST_WEBRTC_ICE_CANDIDATE_STATS_RELATED_PORT:
+ *
+ * Since: 1.28
+ */
+#define GST_WEBRTC_ICE_CANDIDATE_STATS_RELATED_PORT(c) ((c)->ABI.abi.related_port)
+/**
+ * GST_WEBRTC_ICE_CANDIDATE_STATS_USERNAME_FRAGMENT:
+ *
+ * Since: 1.28
+ */
+#define GST_WEBRTC_ICE_CANDIDATE_STATS_USERNAME_FRAGMENT(c) ((c)->ABI.abi.username_fragment)
+/**
+ * GST_WEBRTC_ICE_CANDIDATE_STATS_TCP_TYPE:
+ *
+ * Since: 1.28
+ */
+#define GST_WEBRTC_ICE_CANDIDATE_STATS_TCP_TYPE(c) ((c)->ABI.abi.tcp_type)
+
/**
* GstWebRTCICEOnCandidateFunc:
* @ice: The #GstWebRTCICE
diff --git a/subprojects/gst-plugins-bad/gst-libs/gst/webrtc/nice/nice.c b/subprojects/gst-plugins-bad/gst-libs/gst/webrtc/nice/nice.c
index de6283e589..08251ba93f 100644
--- a/subprojects/gst-plugins-bad/gst-libs/gst/webrtc/nice/nice.c
+++ b/subprojects/gst-plugins-bad/gst-libs/gst/webrtc/nice/nice.c
@@ -551,6 +551,31 @@ gst_webrtc_nice_add_stream (GstWebRTCICE * ice, guint session_id)
return item->stream;
}
+static void
+_fill_candidate_credentials (NiceAgent * agent, NiceCandidate * candidate)
+{
+
+ if (!candidate->username || !candidate->password) {
+ gboolean got_credentials;
+ gchar *ufrag, *password;
+
+ got_credentials =
+ nice_agent_get_local_credentials (agent, candidate->stream_id, &ufrag,
+ &password);
+ g_warn_if_fail (got_credentials);
+
+ if (!candidate->username)
+ candidate->username = ufrag;
+ else
+ g_free (ufrag);
+
+ if (!candidate->password)
+ candidate->password = password;
+ else
+ g_free (password);
+ }
+}
+
static void
_on_new_candidate (NiceAgent * agent, NiceCandidate * candidate,
GstWebRTCNice * ice)
@@ -565,24 +590,7 @@ _on_new_candidate (NiceAgent * agent, NiceCandidate * candidate,
return;
}
- if (!candidate->username || !candidate->password) {
- gboolean got_credentials;
- gchar *ufrag, *password;
-
- got_credentials = nice_agent_get_local_credentials (ice->priv->nice_agent,
- candidate->stream_id, &ufrag, &password);
- g_warn_if_fail (got_credentials);
-
- if (!candidate->username)
- candidate->username = ufrag;
- else
- g_free (ufrag);
-
- if (!candidate->password)
- candidate->password = password;
- else
- g_free (password);
- }
+ _fill_candidate_credentials (agent, candidate);
attr = nice_agent_generate_local_candidate_sdp (agent, candidate);
@@ -1084,18 +1092,52 @@ _populate_candidate_stats (GstWebRTCNice * ice, NiceCandidate * cand,
g_assert (cand != NULL);
nice_address_to_string (&cand->addr, ipaddr);
- stats->port = nice_address_get_port (&cand->addr);
- stats->ipaddr = g_strdup (ipaddr);
- stats->stream_id = stream->stream_id;
- stats->type = nice_candidate_type_to_string (cand->type);
- stats->prio = cand->priority;
- stats->proto =
+ GST_WEBRTC_ICE_CANDIDATE_STATS_PORT (stats) =
+ nice_address_get_port (&cand->addr);
+ GST_WEBRTC_ICE_CANDIDATE_STATS_ADDRESS (stats) = g_strdup (ipaddr);
+ GST_WEBRTC_ICE_CANDIDATE_STATS_STREAM_ID (stats) = stream->stream_id;
+ GST_WEBRTC_ICE_CANDIDATE_STATS_TYPE (stats) =
+ nice_candidate_type_to_string (cand->type);
+ GST_WEBRTC_ICE_CANDIDATE_STATS_PRIORITY (stats) = cand->priority;
+ GST_WEBRTC_ICE_CANDIDATE_STATS_PROTOCOL (stats) =
cand->transport == NICE_CANDIDATE_TRANSPORT_UDP ? "udp" : "tcp";
if (is_local) {
- if (cand->type == NICE_CANDIDATE_TYPE_RELAYED)
- stats->relay_proto = gst_webrtc_nice_get_candidate_relay_protocol (ice->priv->turn_server);
- stats->url = gst_webrtc_nice_get_candidate_server_url (ice, cand);
+ if (cand->type == NICE_CANDIDATE_TYPE_RELAYED) {
+ NiceAddress relay_address;
+ nice_candidate_relay_address (cand, &relay_address);
+
+ GST_WEBRTC_ICE_CANDIDATE_STATS_RELATED_ADDRESS (stats) =
+ nice_address_dup_string (&relay_address);
+ GST_WEBRTC_ICE_CANDIDATE_STATS_RELATED_PORT (stats) =
+ nice_address_get_port (&relay_address);
+
+ GST_WEBRTC_ICE_CANDIDATE_STATS_RELAY_PROTOCOL (stats) =
+ gst_webrtc_nice_get_candidate_relay_protocol (ice->priv->turn_server);
+ }
+ GST_WEBRTC_ICE_CANDIDATE_STATS_URL (stats) =
+ gst_webrtc_nice_get_candidate_server_url (ice, cand);
}
+
+ GST_WEBRTC_ICE_CANDIDATE_STATS_FOUNDATION (stats) =
+ g_strdup (cand->foundation);
+
+ switch (cand->transport) {
+ case NICE_CANDIDATE_TRANSPORT_UDP:
+ GST_WEBRTC_ICE_CANDIDATE_STATS_TCP_TYPE (stats) = NULL;
+ break;
+ case NICE_CANDIDATE_TRANSPORT_TCP_ACTIVE:
+ GST_WEBRTC_ICE_CANDIDATE_STATS_TCP_TYPE (stats) = "active";
+ break;
+ case NICE_CANDIDATE_TRANSPORT_TCP_PASSIVE:
+ GST_WEBRTC_ICE_CANDIDATE_STATS_TCP_TYPE (stats) = "passive";
+ break;
+ case NICE_CANDIDATE_TRANSPORT_TCP_SO:
+ GST_WEBRTC_ICE_CANDIDATE_STATS_TCP_TYPE (stats) = "so";
+ break;
+ };
+
+ GST_WEBRTC_ICE_CANDIDATE_STATS_USERNAME_FRAGMENT (stats) =
+ g_strdup (cand->username);
}
static void
@@ -1166,6 +1208,9 @@ gst_webrtc_nice_get_selected_pair (GstWebRTCICE * ice,
if (stream) {
if (nice_agent_get_selected_pair (nice->priv->nice_agent, stream->stream_id,
NICE_COMPONENT_TYPE_RTP, &local_cand, &remote_cand)) {
+ _fill_candidate_credentials (nice->priv->nice_agent, local_cand);
+ _fill_candidate_credentials (nice->priv->nice_agent, remote_cand);
+
*local_stats = g_new0 (GstWebRTCICECandidateStats, 1);
_populate_candidate_stats (nice, local_cand, stream, *local_stats, TRUE);
diff --git a/subprojects/gst-plugins-bad/gst-libs/gst/webrtc/webrtc_fwd.h b/subprojects/gst-plugins-bad/gst-libs/gst/webrtc/webrtc_fwd.h
index 0bb01f3241..492981ae8a 100644
--- a/subprojects/gst-plugins-bad/gst-libs/gst/webrtc/webrtc_fwd.h
+++ b/subprojects/gst-plugins-bad/gst-libs/gst/webrtc/webrtc_fwd.h
@@ -70,11 +70,6 @@ typedef struct _GstWebRTCDTLSTransportClass GstWebRTCDTLSTransportClass;
typedef struct _GstWebRTCICE GstWebRTCICE;
typedef struct _GstWebRTCICEClass GstWebRTCICEClass;
-/**
- * GstWebRTCICECandidateStats:
- *
- * Since: 1.22
- */
typedef struct _GstWebRTCICECandidateStats GstWebRTCICECandidateStats;
/**
diff --git a/subprojects/gst-plugins-bad/tests/check/elements/webrtcbin.c b/subprojects/gst-plugins-bad/tests/check/elements/webrtcbin.c
index ca73b149b3..78a6149a55 100644
--- a/subprojects/gst-plugins-bad/tests/check/elements/webrtcbin.c
+++ b/subprojects/gst-plugins-bad/tests/check/elements/webrtcbin.c
@@ -1748,6 +1748,7 @@ validate_candidate_stats (const GstStructure * s, const GstStructure * stats)
guint port;
guint64 priority;
gchar *address, *candidateType, *protocol;
+ gchar *foundation, *username_fragment;
fail_unless (gst_structure_get (s, "address", G_TYPE_STRING, &address, NULL));
fail_unless (gst_structure_get (s, "port", G_TYPE_UINT, &port, NULL));
@@ -1759,9 +1760,39 @@ validate_candidate_stats (const GstStructure * s, const GstStructure * stats)
fail_unless (strcmp (protocol, "udp") || strcmp (protocol, "tcp"));
+ fail_unless (gst_structure_get (s, "foundation", G_TYPE_STRING, &foundation,
+ NULL));
+ fail_unless (gst_structure_get (s, "username-fragment", G_TYPE_STRING,
+ &username_fragment, NULL));
+
+ if (strcmp (candidateType, "host")) {
+ guint related_port;
+ gchar *related_address;
+ fail_unless (gst_structure_get (s, "related-address", G_TYPE_STRING,
+ &related_address, NULL));
+ fail_unless (gst_structure_get (s, "related-port", G_TYPE_UINT,
+ &related_port, NULL));
+ g_free (related_address);
+ } else {
+ fail_if (gst_structure_has_field (s, "related-address"));
+ fail_if (gst_structure_has_field (s, "related-port"));
+ }
+
+ if (!strcmp (protocol, "tcp")) {
+ gchar *tcp_type;
+ fail_unless (gst_structure_get (s, "tcp-type", G_TYPE_STRING, &tcp_type,
+ NULL));
+ fail_unless (strcmp (tcp_type, "so") || strcmp (tcp_type, "active")
+ || strcmp (tcp_type, "passive"));
+ g_free (tcp_type);
+ } else {
+ fail_if (gst_structure_has_field (s, "tcp-type"));
+ }
g_free (address);
g_free (candidateType);
g_free (protocol);
+ g_free (foundation);
+ g_free (username_fragment);
}
static void