Reland "Structured ICE logging via RtcEventLog."
This is a reland of eed5aa8904d09179971d3f4e7e10c109d7c62bfc
Original change's description:
> Structured ICE logging via RtcEventLog.
>
> This change list contains the structured logging module for ICE using
> the RtcEventLog infrastructure, and also extension to the log parser
> and analyzer.
>
> Bug: None
> Change-Id: I6539cf282155c2cde4d3161c53500c0746671a02
> Reviewed-on: https://webrtc-review.googlesource.com/34622
> Commit-Queue: Qingsi Wang <qingsi@google.com>
> Reviewed-by: Björn Terelius <terelius@webrtc.org>
> Reviewed-by: Peter Thatcher <pthatcher@webrtc.org>
> Cr-Commit-Position: refs/heads/master@{#21816}
TBR=pthatcher@webrtc.org,terelius@webrtc.org,deadbeef@webrtc.org
Bug: None
Change-Id: I3df585bf636315ceb0273967146111346a83be86
Reviewed-on: https://webrtc-review.googlesource.com/47545
Commit-Queue: Qingsi Wang <qingsi@google.com>
Reviewed-by: Qingsi Wang <qingsi@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#21881}
diff --git a/logging/BUILD.gn b/logging/BUILD.gn
index f1f2d91..b65c0b8 100644
--- a/logging/BUILD.gn
+++ b/logging/BUILD.gn
@@ -164,6 +164,7 @@
defines = []
deps = [
+ ":ice_log",
":rtc_event_audio",
":rtc_event_bwe",
":rtc_event_log_api",
@@ -221,6 +222,7 @@
defines = []
deps = [
+ ":ice_log",
":rtc_event_log_api",
":rtc_event_log_impl_encoder",
":rtc_event_log_impl_output",
@@ -263,6 +265,7 @@
]
deps = [
+ ":ice_log",
":rtc_event_bwe",
":rtc_event_log2_proto",
":rtc_event_log_api",
@@ -400,6 +403,28 @@
}
}
+rtc_source_set("ice_log") {
+ sources = [
+ "rtc_event_log/events/rtc_event_ice_candidate_pair.cc",
+ "rtc_event_log/events/rtc_event_ice_candidate_pair.h",
+ "rtc_event_log/events/rtc_event_ice_candidate_pair_config.cc",
+ "rtc_event_log/events/rtc_event_ice_candidate_pair_config.h",
+ "rtc_event_log/icelogger.cc",
+ "rtc_event_log/icelogger.h",
+ ]
+
+ deps = [
+ ":rtc_event_log_api",
+ "../api:libjingle_logging_api",
+ "../rtc_base:rtc_base_approved",
+ ]
+
+ if (!build_with_chromium && is_clang) {
+ # Suppress warnings from the Chromium Clang plugin (bugs.webrtc.org/163).
+ suppressed_configs += [ "//build/config/clang:find_bad_constructs" ]
+ }
+}
+
if (rtc_include_tests) {
rtc_source_set("mocks") {
testonly = true
diff --git a/logging/rtc_event_log/encoder/rtc_event_log_encoder_legacy.cc b/logging/rtc_event_log/encoder/rtc_event_log_encoder_legacy.cc
index 1f02bcc..9ebdcbc 100644
--- a/logging/rtc_event_log/encoder/rtc_event_log_encoder_legacy.cc
+++ b/logging/rtc_event_log/encoder/rtc_event_log_encoder_legacy.cc
@@ -17,6 +17,8 @@
#include "logging/rtc_event_log/events/rtc_event_audio_send_stream_config.h"
#include "logging/rtc_event_log/events/rtc_event_bwe_update_delay_based.h"
#include "logging/rtc_event_log/events/rtc_event_bwe_update_loss_based.h"
+#include "logging/rtc_event_log/events/rtc_event_ice_candidate_pair.h"
+#include "logging/rtc_event_log/events/rtc_event_ice_candidate_pair_config.h"
#include "logging/rtc_event_log/events/rtc_event_probe_cluster_created.h"
#include "logging/rtc_event_log/events/rtc_event_probe_result_failure.h"
#include "logging/rtc_event_log/events/rtc_event_probe_result_success.h"
@@ -103,6 +105,122 @@
RTC_NOTREACHED();
return rtclog::VideoReceiveConfig::RTCP_COMPOUND;
}
+
+rtclog::IceCandidatePairConfig::IceCandidatePairConfigType
+ConvertIceCandidatePairConfigType(IceCandidatePairEventType type) {
+ switch (type) {
+ case IceCandidatePairEventType::kAdded:
+ return rtclog::IceCandidatePairConfig::ADDED;
+ case IceCandidatePairEventType::kUpdated:
+ return rtclog::IceCandidatePairConfig::UPDATED;
+ case IceCandidatePairEventType::kDestroyed:
+ return rtclog::IceCandidatePairConfig::DESTROYED;
+ case IceCandidatePairEventType::kSelected:
+ return rtclog::IceCandidatePairConfig::SELECTED;
+ default:
+ RTC_NOTREACHED();
+ }
+ RTC_NOTREACHED();
+ return rtclog::IceCandidatePairConfig::ADDED;
+}
+
+rtclog::IceCandidatePairConfig::IceCandidateType ConvertIceCandidateType(
+ IceCandidateType type) {
+ switch (type) {
+ case IceCandidateType::kLocal:
+ return rtclog::IceCandidatePairConfig::LOCAL;
+ case IceCandidateType::kStun:
+ return rtclog::IceCandidatePairConfig::STUN;
+ case IceCandidateType::kPrflx:
+ return rtclog::IceCandidatePairConfig::PRFLX;
+ case IceCandidateType::kRelay:
+ return rtclog::IceCandidatePairConfig::RELAY;
+ case IceCandidateType::kUnknown:
+ return rtclog::IceCandidatePairConfig::UNKNOWN_CANDIDATE_TYPE;
+ default:
+ RTC_NOTREACHED();
+ }
+ RTC_NOTREACHED();
+ return rtclog::IceCandidatePairConfig::UNKNOWN_CANDIDATE_TYPE;
+}
+
+rtclog::IceCandidatePairConfig::Protocol ConvertIceCandidatePairProtocol(
+ IceCandidatePairProtocol protocol) {
+ switch (protocol) {
+ case IceCandidatePairProtocol::kUdp:
+ return rtclog::IceCandidatePairConfig::UDP;
+ case IceCandidatePairProtocol::kTcp:
+ return rtclog::IceCandidatePairConfig::TCP;
+ case IceCandidatePairProtocol::kSsltcp:
+ return rtclog::IceCandidatePairConfig::SSLTCP;
+ case IceCandidatePairProtocol::kTls:
+ return rtclog::IceCandidatePairConfig::TLS;
+ case IceCandidatePairProtocol::kUnknown:
+ return rtclog::IceCandidatePairConfig::UNKNOWN_PROTOCOL;
+ default:
+ RTC_NOTREACHED();
+ }
+ RTC_NOTREACHED();
+ return rtclog::IceCandidatePairConfig::UNKNOWN_PROTOCOL;
+}
+
+rtclog::IceCandidatePairConfig::AddressFamily
+ConvertIceCandidatePairAddressFamily(
+ IceCandidatePairAddressFamily address_family) {
+ switch (address_family) {
+ case IceCandidatePairAddressFamily::kIpv4:
+ return rtclog::IceCandidatePairConfig::IPV4;
+ case IceCandidatePairAddressFamily::kIpv6:
+ return rtclog::IceCandidatePairConfig::IPV6;
+ case IceCandidatePairAddressFamily::kUnknown:
+ return rtclog::IceCandidatePairConfig::UNKNOWN_ADDRESS_FAMILY;
+ default:
+ RTC_NOTREACHED();
+ }
+ RTC_NOTREACHED();
+ return rtclog::IceCandidatePairConfig::UNKNOWN_ADDRESS_FAMILY;
+}
+
+rtclog::IceCandidatePairConfig::NetworkType ConvertIceCandidateNetworkType(
+ IceCandidateNetworkType network_type) {
+ switch (network_type) {
+ case IceCandidateNetworkType::kEthernet:
+ return rtclog::IceCandidatePairConfig::ETHERNET;
+ case IceCandidateNetworkType::kLoopback:
+ return rtclog::IceCandidatePairConfig::LOOPBACK;
+ case IceCandidateNetworkType::kWifi:
+ return rtclog::IceCandidatePairConfig::WIFI;
+ case IceCandidateNetworkType::kVpn:
+ return rtclog::IceCandidatePairConfig::VPN;
+ case IceCandidateNetworkType::kCellular:
+ return rtclog::IceCandidatePairConfig::CELLULAR;
+ case IceCandidateNetworkType::kUnknown:
+ return rtclog::IceCandidatePairConfig::UNKNOWN_NETWORK_TYPE;
+ default:
+ RTC_NOTREACHED();
+ }
+ RTC_NOTREACHED();
+ return rtclog::IceCandidatePairConfig::UNKNOWN_NETWORK_TYPE;
+}
+
+rtclog::IceCandidatePairEvent::IceCandidatePairEventType
+ConvertIceCandidatePairEventType(IceCandidatePairEventType type) {
+ switch (type) {
+ case IceCandidatePairEventType::kCheckSent:
+ return rtclog::IceCandidatePairEvent::CHECK_SENT;
+ case IceCandidatePairEventType::kCheckReceived:
+ return rtclog::IceCandidatePairEvent::CHECK_RECEIVED;
+ case IceCandidatePairEventType::kCheckResponseSent:
+ return rtclog::IceCandidatePairEvent::CHECK_RESPONSE_SENT;
+ case IceCandidatePairEventType::kCheckResponseReceived:
+ return rtclog::IceCandidatePairEvent::CHECK_RESPONSE_RECEIVED;
+ default:
+ RTC_NOTREACHED();
+ }
+ RTC_NOTREACHED();
+ return rtclog::IceCandidatePairEvent::CHECK_SENT;
+}
+
} // namespace
std::string RtcEventLogEncoderLegacy::EncodeLogStart(int64_t timestamp_us) {
@@ -171,6 +289,17 @@
return EncodeBweUpdateLossBased(rtc_event);
}
+ case RtcEvent::Type::IceCandidatePairConfig: {
+ auto& rtc_event =
+ static_cast<const RtcEventIceCandidatePairConfig&>(event);
+ return EncodeIceCandidatePairConfig(rtc_event);
+ }
+
+ case RtcEvent::Type::IceCandidatePairEvent: {
+ auto& rtc_event = static_cast<const RtcEventIceCandidatePair&>(event);
+ return EncodeIceCandidatePairEvent(rtc_event);
+ }
+
case RtcEvent::Type::ProbeClusterCreated: {
auto& rtc_event = static_cast<const RtcEventProbeClusterCreated&>(event);
return EncodeProbeClusterCreated(rtc_event);
@@ -343,6 +472,48 @@
return Serialize(&rtclog_event);
}
+std::string RtcEventLogEncoderLegacy::EncodeIceCandidatePairConfig(
+ const RtcEventIceCandidatePairConfig& event) {
+ rtclog::Event encoded_rtc_event;
+ encoded_rtc_event.set_timestamp_us(event.timestamp_us_);
+ encoded_rtc_event.set_type(rtclog::Event::ICE_CANDIDATE_PAIR_CONFIG);
+
+ auto encoded_ice_event =
+ encoded_rtc_event.mutable_ice_candidate_pair_config();
+ encoded_ice_event->set_config_type(
+ ConvertIceCandidatePairConfigType(event.type_));
+ encoded_ice_event->set_candidate_pair_id(event.candidate_pair_id_);
+ const auto& desc = event.candidate_pair_desc_;
+ encoded_ice_event->set_local_candidate_type(
+ ConvertIceCandidateType(desc.local_candidate_type));
+ encoded_ice_event->set_local_relay_protocol(
+ ConvertIceCandidatePairProtocol(desc.local_relay_protocol));
+ encoded_ice_event->set_local_network_type(
+ ConvertIceCandidateNetworkType(desc.local_network_type));
+ encoded_ice_event->set_local_address_family(
+ ConvertIceCandidatePairAddressFamily(desc.local_address_family));
+ encoded_ice_event->set_remote_candidate_type(
+ ConvertIceCandidateType(desc.remote_candidate_type));
+ encoded_ice_event->set_remote_address_family(
+ ConvertIceCandidatePairAddressFamily(desc.remote_address_family));
+ encoded_ice_event->set_candidate_pair_protocol(
+ ConvertIceCandidatePairProtocol(desc.candidate_pair_protocol));
+ return Serialize(&encoded_rtc_event);
+}
+
+std::string RtcEventLogEncoderLegacy::EncodeIceCandidatePairEvent(
+ const RtcEventIceCandidatePair& event) {
+ rtclog::Event encoded_rtc_event;
+ encoded_rtc_event.set_timestamp_us(event.timestamp_us_);
+ encoded_rtc_event.set_type(rtclog::Event::ICE_CANDIDATE_PAIR_EVENT);
+
+ auto encoded_ice_event = encoded_rtc_event.mutable_ice_candidate_pair_event();
+ encoded_ice_event->set_event_type(
+ ConvertIceCandidatePairEventType(event.type_));
+ encoded_ice_event->set_candidate_pair_id(event.candidate_pair_id_);
+ return Serialize(&encoded_rtc_event);
+}
+
std::string RtcEventLogEncoderLegacy::EncodeProbeClusterCreated(
const RtcEventProbeClusterCreated& event) {
rtclog::Event rtclog_event;
diff --git a/logging/rtc_event_log/encoder/rtc_event_log_encoder_legacy.h b/logging/rtc_event_log/encoder/rtc_event_log_encoder_legacy.h
index 63102c5..87db039 100644
--- a/logging/rtc_event_log/encoder/rtc_event_log_encoder_legacy.h
+++ b/logging/rtc_event_log/encoder/rtc_event_log_encoder_legacy.h
@@ -32,6 +32,8 @@
class RtcEventAudioSendStreamConfig;
class RtcEventBweUpdateDelayBased;
class RtcEventBweUpdateLossBased;
+class RtcEventIceCandidatePairConfig;
+class RtcEventIceCandidatePair;
class RtcEventLoggingStarted;
class RtcEventLoggingStopped;
class RtcEventProbeClusterCreated;
@@ -71,6 +73,10 @@
std::string EncodeBweUpdateDelayBased(
const RtcEventBweUpdateDelayBased& event);
std::string EncodeBweUpdateLossBased(const RtcEventBweUpdateLossBased& event);
+ std::string EncodeIceCandidatePairConfig(
+ const RtcEventIceCandidatePairConfig& event);
+ std::string EncodeIceCandidatePairEvent(
+ const RtcEventIceCandidatePair& event);
std::string EncodeProbeClusterCreated(
const RtcEventProbeClusterCreated& event);
std::string EncodeProbeResultFailure(const RtcEventProbeResultFailure& event);
diff --git a/logging/rtc_event_log/events/rtc_event.h b/logging/rtc_event_log/events/rtc_event.h
index 6410698..25820ef 100644
--- a/logging/rtc_event_log/events/rtc_event.h
+++ b/logging/rtc_event_log/events/rtc_event.h
@@ -37,6 +37,8 @@
AudioSendStreamConfig,
BweUpdateDelayBased,
BweUpdateLossBased,
+ IceCandidatePairConfig,
+ IceCandidatePairEvent,
ProbeClusterCreated,
ProbeResultFailure,
ProbeResultSuccess,
diff --git a/logging/rtc_event_log/events/rtc_event_ice_candidate_pair.cc b/logging/rtc_event_log/events/rtc_event_ice_candidate_pair.cc
new file mode 100644
index 0000000..b3d084e
--- /dev/null
+++ b/logging/rtc_event_log/events/rtc_event_ice_candidate_pair.cc
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "logging/rtc_event_log/events/rtc_event_ice_candidate_pair.h"
+
+namespace webrtc {
+
+RtcEventIceCandidatePair::RtcEventIceCandidatePair(
+ IceCandidatePairEventType type,
+ uint32_t candidate_pair_id)
+ : type_(type), candidate_pair_id_(candidate_pair_id) {}
+
+RtcEventIceCandidatePair::~RtcEventIceCandidatePair() = default;
+
+RtcEvent::Type RtcEventIceCandidatePair::GetType() const {
+ return RtcEvent::Type::IceCandidatePairEvent;
+}
+
+bool RtcEventIceCandidatePair::IsConfigEvent() const {
+ return false;
+}
+
+} // namespace webrtc
diff --git a/logging/rtc_event_log/events/rtc_event_ice_candidate_pair.h b/logging/rtc_event_log/events/rtc_event_ice_candidate_pair.h
new file mode 100644
index 0000000..b6cd61f
--- /dev/null
+++ b/logging/rtc_event_log/events/rtc_event_ice_candidate_pair.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef LOGGING_RTC_EVENT_LOG_EVENTS_RTC_EVENT_ICE_CANDIDATE_PAIR_H_
+#define LOGGING_RTC_EVENT_LOG_EVENTS_RTC_EVENT_ICE_CANDIDATE_PAIR_H_
+
+#include "logging/rtc_event_log/events/rtc_event.h"
+
+#include <string>
+
+namespace webrtc {
+
+enum class IceCandidatePairEventType {
+ // Config event types for events related to the candiate pair creation and
+ // life-cycle management.
+ kAdded,
+ kUpdated,
+ kDestroyed,
+ kSelected,
+ // Non-config event types.
+ kCheckSent,
+ kCheckReceived,
+ kCheckResponseSent,
+ kCheckResponseReceived,
+};
+
+class RtcEventIceCandidatePair final : public RtcEvent {
+ public:
+ RtcEventIceCandidatePair(IceCandidatePairEventType type,
+ uint32_t candidate_pair_id);
+
+ ~RtcEventIceCandidatePair() override;
+
+ Type GetType() const override;
+
+ bool IsConfigEvent() const override;
+
+ const IceCandidatePairEventType type_;
+ const uint32_t candidate_pair_id_;
+};
+
+} // namespace webrtc
+
+#endif // LOGGING_RTC_EVENT_LOG_EVENTS_RTC_EVENT_ICE_CANDIDATE_PAIR_H_
diff --git a/logging/rtc_event_log/events/rtc_event_ice_candidate_pair_config.cc b/logging/rtc_event_log/events/rtc_event_ice_candidate_pair_config.cc
new file mode 100644
index 0000000..33fd8c7
--- /dev/null
+++ b/logging/rtc_event_log/events/rtc_event_ice_candidate_pair_config.cc
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "logging/rtc_event_log/events/rtc_event_ice_candidate_pair_config.h"
+
+namespace webrtc {
+
+IceCandidatePairDescription::IceCandidatePairDescription() {
+ local_candidate_type = IceCandidateType::kUnknown;
+ local_relay_protocol = IceCandidatePairProtocol::kUnknown;
+ local_network_type = IceCandidateNetworkType::kUnknown;
+ local_address_family = IceCandidatePairAddressFamily::kUnknown;
+ remote_candidate_type = IceCandidateType::kUnknown;
+ remote_address_family = IceCandidatePairAddressFamily::kUnknown;
+ candidate_pair_protocol = IceCandidatePairProtocol::kUnknown;
+}
+
+IceCandidatePairDescription::IceCandidatePairDescription(
+ const IceCandidatePairDescription& other) {
+ local_candidate_type = other.local_candidate_type;
+ local_relay_protocol = other.local_relay_protocol;
+ local_network_type = other.local_network_type;
+ local_address_family = other.local_address_family;
+ remote_candidate_type = other.remote_candidate_type;
+ remote_address_family = other.remote_address_family;
+ candidate_pair_protocol = other.candidate_pair_protocol;
+}
+
+IceCandidatePairDescription::~IceCandidatePairDescription() {}
+
+RtcEventIceCandidatePairConfig::RtcEventIceCandidatePairConfig(
+ IceCandidatePairEventType type,
+ uint32_t candidate_pair_id,
+ const IceCandidatePairDescription& candidate_pair_desc)
+ : type_(type),
+ candidate_pair_id_(candidate_pair_id),
+ candidate_pair_desc_(candidate_pair_desc) {}
+
+RtcEventIceCandidatePairConfig::~RtcEventIceCandidatePairConfig() = default;
+
+RtcEvent::Type RtcEventIceCandidatePairConfig::GetType() const {
+ return RtcEvent::Type::IceCandidatePairConfig;
+}
+
+// The ICE candidate pair config event is not equivalent to a RtcEventLog config
+// event.
+bool RtcEventIceCandidatePairConfig::IsConfigEvent() const {
+ return false;
+}
+
+} // namespace webrtc
diff --git a/logging/rtc_event_log/events/rtc_event_ice_candidate_pair_config.h b/logging/rtc_event_log/events/rtc_event_ice_candidate_pair_config.h
new file mode 100644
index 0000000..70c81bf
--- /dev/null
+++ b/logging/rtc_event_log/events/rtc_event_ice_candidate_pair_config.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef LOGGING_RTC_EVENT_LOG_EVENTS_RTC_EVENT_ICE_CANDIDATE_PAIR_CONFIG_H_
+#define LOGGING_RTC_EVENT_LOG_EVENTS_RTC_EVENT_ICE_CANDIDATE_PAIR_CONFIG_H_
+
+#include "logging/rtc_event_log/events/rtc_event.h"
+
+#include "logging/rtc_event_log/events/rtc_event_ice_candidate_pair.h"
+
+#include <string>
+
+namespace webrtc {
+
+// TODO(qingsi): Change the names of candidate types to "host", "srflx", "prflx"
+// and "relay" after the naming is spec-compliant in the signaling part
+enum class IceCandidateType {
+ kLocal,
+ kStun,
+ kPrflx,
+ kRelay,
+ kUnknown,
+};
+
+enum class IceCandidatePairProtocol {
+ kUdp,
+ kTcp,
+ kSsltcp,
+ kTls,
+ kUnknown,
+};
+
+enum class IceCandidatePairAddressFamily {
+ kIpv4,
+ kIpv6,
+ kUnknown,
+};
+
+enum class IceCandidateNetworkType {
+ kEthernet,
+ kLoopback,
+ kWifi,
+ kVpn,
+ kCellular,
+ kUnknown,
+};
+
+class IceCandidatePairDescription {
+ public:
+ IceCandidatePairDescription();
+ explicit IceCandidatePairDescription(
+ const IceCandidatePairDescription& other);
+
+ ~IceCandidatePairDescription();
+
+ IceCandidateType local_candidate_type;
+ IceCandidatePairProtocol local_relay_protocol;
+ IceCandidateNetworkType local_network_type;
+ IceCandidatePairAddressFamily local_address_family;
+ IceCandidateType remote_candidate_type;
+ IceCandidatePairAddressFamily remote_address_family;
+ IceCandidatePairProtocol candidate_pair_protocol;
+};
+
+class RtcEventIceCandidatePairConfig final : public RtcEvent {
+ public:
+ RtcEventIceCandidatePairConfig(
+ IceCandidatePairEventType type,
+ uint32_t candidate_pair_id,
+ const IceCandidatePairDescription& candidate_pair_desc);
+
+ ~RtcEventIceCandidatePairConfig() override;
+
+ Type GetType() const override;
+
+ bool IsConfigEvent() const override;
+
+ const IceCandidatePairEventType type_;
+ const uint32_t candidate_pair_id_;
+ const IceCandidatePairDescription candidate_pair_desc_;
+};
+
+} // namespace webrtc
+
+#endif // LOGGING_RTC_EVENT_LOG_EVENTS_RTC_EVENT_ICE_CANDIDATE_PAIR_CONFIG_H_
diff --git a/logging/rtc_event_log/icelogger.cc b/logging/rtc_event_log/icelogger.cc
new file mode 100644
index 0000000..108f966
--- /dev/null
+++ b/logging/rtc_event_log/icelogger.cc
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "logging/rtc_event_log/icelogger.h"
+
+#include "logging/rtc_event_log/rtc_event_log.h"
+#include "rtc_base/ptr_util.h"
+
+namespace webrtc {
+
+IceEventLog::IceEventLog() {}
+IceEventLog::~IceEventLog() {}
+
+bool IceEventLog::IsIceCandidatePairConfigEvent(
+ IceCandidatePairEventType type) {
+ return (type == IceCandidatePairEventType::kAdded) ||
+ (type == IceCandidatePairEventType::kUpdated) ||
+ (type == IceCandidatePairEventType::kDestroyed) ||
+ (type == IceCandidatePairEventType::kSelected);
+}
+
+void IceEventLog::LogCandidatePairEvent(
+ IceCandidatePairEventType type,
+ uint32_t candidate_pair_id,
+ const IceCandidatePairDescription& candidate_pair_desc) {
+ if (event_log_ == nullptr) {
+ return;
+ }
+ if (IsIceCandidatePairConfigEvent(type)) {
+ candidate_pair_desc_by_id_[candidate_pair_id] = candidate_pair_desc;
+ event_log_->Log(rtc::MakeUnique<RtcEventIceCandidatePairConfig>(
+ type, candidate_pair_id, candidate_pair_desc));
+ return;
+ }
+ event_log_->Log(
+ rtc::MakeUnique<RtcEventIceCandidatePair>(type, candidate_pair_id));
+}
+
+void IceEventLog::DumpCandidatePairDescriptionToMemoryAsConfigEvents() const {
+ for (const auto& desc_id_pair : candidate_pair_desc_by_id_) {
+ event_log_->Log(rtc::MakeUnique<RtcEventIceCandidatePairConfig>(
+ IceCandidatePairEventType::kUpdated, desc_id_pair.first,
+ desc_id_pair.second));
+ }
+}
+
+} // namespace webrtc
diff --git a/logging/rtc_event_log/icelogger.h b/logging/rtc_event_log/icelogger.h
new file mode 100644
index 0000000..b3689c7
--- /dev/null
+++ b/logging/rtc_event_log/icelogger.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef LOGGING_RTC_EVENT_LOG_ICELOGGER_H_
+#define LOGGING_RTC_EVENT_LOG_ICELOGGER_H_
+
+#include <unordered_map>
+
+#include "logging/rtc_event_log/events/rtc_event_ice_candidate_pair.h"
+#include "logging/rtc_event_log/events/rtc_event_ice_candidate_pair_config.h"
+
+namespace webrtc {
+
+class RtcEventLog;
+
+// IceEventLog wraps RtcEventLog and provides structural logging of ICE-specific
+// events. The logged events are serialized with other RtcEvent's if protobuf is
+// enabled in the build.
+class IceEventLog {
+ public:
+ IceEventLog();
+ ~IceEventLog();
+ void set_event_log(RtcEventLog* event_log) { event_log_ = event_log; }
+ void LogCandidatePairEvent(
+ IceCandidatePairEventType type,
+ uint32_t candidate_pair_id,
+ const IceCandidatePairDescription& candidate_pair_desc);
+ // This method constructs a config event for each candidate pair with their
+ // description and logs these config events. It is intended to be called when
+ // logging starts to ensure that we have at least one config for each
+ // candidate pair id.
+ void DumpCandidatePairDescriptionToMemoryAsConfigEvents() const;
+
+ private:
+ bool IsIceCandidatePairConfigEvent(IceCandidatePairEventType type);
+
+ RtcEventLog* event_log_ = nullptr;
+ std::unordered_map<uint32_t, IceCandidatePairDescription>
+ candidate_pair_desc_by_id_;
+};
+
+} // namespace webrtc
+
+#endif // LOGGING_RTC_EVENT_LOG_ICELOGGER_H_
diff --git a/logging/rtc_event_log/rtc_event_log.proto b/logging/rtc_event_log/rtc_event_log.proto
index 8d2e22a..bfac4f6 100644
--- a/logging/rtc_event_log/rtc_event_log.proto
+++ b/logging/rtc_event_log/rtc_event_log.proto
@@ -41,6 +41,8 @@
BWE_PROBE_CLUSTER_CREATED_EVENT = 17;
BWE_PROBE_RESULT_EVENT = 18;
ALR_STATE_EVENT = 19;
+ ICE_CANDIDATE_PAIR_CONFIG = 20;
+ ICE_CANDIDATE_PAIR_EVENT = 21;
}
// required - Indicates the type of this event
@@ -85,6 +87,12 @@
// required if type == ALR_STATE_EVENT
AlrState alr_state = 19;
+
+ // required if type == ICE_CANDIDATE_PAIR_CONFIG
+ IceCandidatePairConfig ice_candidate_pair_config = 20;
+
+ // required if type == ICE_CANDIDATE_PAIR_EVENT
+ IceCandidatePairEvent ice_candidate_pair_event = 21;
}
}
@@ -323,3 +331,85 @@
// required - If we are in ALR or not.
optional bool in_alr = 1;
}
+
+message IceCandidatePairConfig {
+ enum IceCandidatePairConfigType {
+ ADDED = 0;
+ UPDATED = 1;
+ DESTROYED = 2;
+ SELECTED = 3;
+ }
+
+ enum IceCandidateType {
+ LOCAL = 0;
+ STUN = 1;
+ PRFLX = 2;
+ RELAY = 3;
+ UNKNOWN_CANDIDATE_TYPE = 4;
+ }
+
+ enum Protocol {
+ UDP = 0;
+ TCP = 1;
+ SSLTCP = 2;
+ TLS = 3;
+ UNKNOWN_PROTOCOL = 4;
+ }
+
+ enum AddressFamily {
+ IPV4 = 0;
+ IPV6 = 1;
+ UNKNOWN_ADDRESS_FAMILY = 2;
+ }
+
+ enum NetworkType {
+ ETHERNET = 0;
+ LOOPBACK = 1;
+ WIFI = 2;
+ VPN = 3;
+ CELLULAR = 4;
+ UNKNOWN_NETWORK_TYPE = 5;
+ }
+
+ // required
+ optional IceCandidatePairConfigType config_type = 1;
+
+ // required
+ optional uint32 candidate_pair_id = 2;
+
+ // required
+ optional IceCandidateType local_candidate_type = 3;
+
+ // required
+ optional Protocol local_relay_protocol = 4;
+
+ // required
+ optional NetworkType local_network_type = 5;
+
+ // required
+ optional AddressFamily local_address_family = 6;
+
+ // required
+ optional IceCandidateType remote_candidate_type = 7;
+
+ // required
+ optional AddressFamily remote_address_family = 8;
+
+ // required
+ optional Protocol candidate_pair_protocol = 9;
+}
+
+message IceCandidatePairEvent {
+ enum IceCandidatePairEventType {
+ CHECK_SENT = 0;
+ CHECK_RECEIVED = 1;
+ CHECK_RESPONSE_SENT = 2;
+ CHECK_RESPONSE_RECEIVED = 3;
+ }
+
+ // required
+ optional IceCandidatePairEventType event_type = 1;
+
+ // required
+ optional uint32 candidate_pair_id = 2;
+}
diff --git a/logging/rtc_event_log/rtc_event_log2stats.cc b/logging/rtc_event_log/rtc_event_log2stats.cc
index f38322d..6b0c4c0 100644
--- a/logging/rtc_event_log/rtc_event_log2stats.cc
+++ b/logging/rtc_event_log/rtc_event_log2stats.cc
@@ -166,6 +166,10 @@
return "BWE_PROBE_RESULT";
case webrtc::rtclog::Event::ALR_STATE_EVENT:
return "ALR_STATE_EVENT";
+ case webrtc::rtclog::Event::ICE_CANDIDATE_PAIR_CONFIG:
+ return "ICE_CANDIDATE_PAIR_CONFIG";
+ case webrtc::rtclog::Event::ICE_CANDIDATE_PAIR_EVENT:
+ return "ICE_CANDIDATE_PAIR_EVENT";
}
RTC_NOTREACHED();
return "UNKNOWN_EVENT";
diff --git a/logging/rtc_event_log/rtc_event_log2text.cc b/logging/rtc_event_log/rtc_event_log2text.cc
index 42ff732..c71a2b8 100644
--- a/logging/rtc_event_log/rtc_event_log2text.cc
+++ b/logging/rtc_event_log/rtc_event_log2text.cc
@@ -60,6 +60,7 @@
DEFINE_bool(playout, true, "Use --noplayout to exclude audio playout events.");
DEFINE_bool(ana, true, "Use --noana to exclude ANA events.");
DEFINE_bool(probe, true, "Use --noprobe to exclude probe events.");
+DEFINE_bool(ice, true, "Use --noice to exclude ICE events.");
DEFINE_bool(print_full_packets,
false,
@@ -796,6 +797,34 @@
event_recognized = true;
break;
}
+
+ case webrtc::ParsedRtcEventLog::ICE_CANDIDATE_PAIR_CONFIG: {
+ if (FLAG_ice) {
+ webrtc::ParsedRtcEventLog::IceCandidatePairConfig ice_cp_config =
+ parsed_stream.GetIceCandidatePairConfig(i);
+ // TODO(qingsi): convert the numeric representation of states to text
+ std::cout << parsed_stream.GetTimestamp(i)
+ << "\tICE_CANDIDATE_PAIR_CONFIG"
+ << "\ttype=" << static_cast<int>(ice_cp_config.type)
+ << std::endl;
+ }
+ event_recognized = true;
+ break;
+ }
+
+ case webrtc::ParsedRtcEventLog::ICE_CANDIDATE_PAIR_EVENT: {
+ if (FLAG_ice) {
+ webrtc::ParsedRtcEventLog::IceCandidatePairEvent ice_cp_event =
+ parsed_stream.GetIceCandidatePairEvent(i);
+ // TODO(qingsi): convert the numeric representation of states to text
+ std::cout << parsed_stream.GetTimestamp(i)
+ << "\tICE_CANDIDATE_PAIR_EVENT"
+ << "\ttype=" << static_cast<int>(ice_cp_event.type)
+ << std::endl;
+ }
+ event_recognized = true;
+ break;
+ }
}
if (!event_recognized) {
diff --git a/logging/rtc_event_log/rtc_event_log_parser.cc b/logging/rtc_event_log/rtc_event_log_parser.cc
index 194da57..6978928 100644
--- a/logging/rtc_event_log/rtc_event_log_parser.cc
+++ b/logging/rtc_event_log/rtc_event_log_parser.cc
@@ -76,6 +76,10 @@
return ParsedRtcEventLog::EventType::BWE_PROBE_RESULT_EVENT;
case rtclog::Event::ALR_STATE_EVENT:
return ParsedRtcEventLog::EventType::ALR_STATE_EVENT;
+ case rtclog::Event::ICE_CANDIDATE_PAIR_CONFIG:
+ return ParsedRtcEventLog::EventType::ICE_CANDIDATE_PAIR_CONFIG;
+ case rtclog::Event::ICE_CANDIDATE_PAIR_EVENT:
+ return ParsedRtcEventLog::EventType::ICE_CANDIDATE_PAIR_EVENT;
}
return ParsedRtcEventLog::EventType::UNKNOWN_EVENT;
}
@@ -94,6 +98,108 @@
return BandwidthUsage::kBwNormal;
}
+IceCandidatePairEventType GetRuntimeIceCandidatePairConfigType(
+ rtclog::IceCandidatePairConfig::IceCandidatePairConfigType type) {
+ switch (type) {
+ case rtclog::IceCandidatePairConfig::ADDED:
+ return IceCandidatePairEventType::kAdded;
+ case rtclog::IceCandidatePairConfig::UPDATED:
+ return IceCandidatePairEventType::kUpdated;
+ case rtclog::IceCandidatePairConfig::DESTROYED:
+ return IceCandidatePairEventType::kDestroyed;
+ case rtclog::IceCandidatePairConfig::SELECTED:
+ return IceCandidatePairEventType::kSelected;
+ }
+ RTC_NOTREACHED();
+ return IceCandidatePairEventType::kAdded;
+}
+
+IceCandidateType GetRuntimeIceCandidateType(
+ rtclog::IceCandidatePairConfig::IceCandidateType type) {
+ switch (type) {
+ case rtclog::IceCandidatePairConfig::LOCAL:
+ return IceCandidateType::kLocal;
+ case rtclog::IceCandidatePairConfig::STUN:
+ return IceCandidateType::kStun;
+ case rtclog::IceCandidatePairConfig::PRFLX:
+ return IceCandidateType::kPrflx;
+ case rtclog::IceCandidatePairConfig::RELAY:
+ return IceCandidateType::kRelay;
+ case rtclog::IceCandidatePairConfig::UNKNOWN_CANDIDATE_TYPE:
+ return IceCandidateType::kUnknown;
+ }
+ RTC_NOTREACHED();
+ return IceCandidateType::kUnknown;
+}
+
+IceCandidatePairProtocol GetRuntimeIceCandidatePairProtocol(
+ rtclog::IceCandidatePairConfig::Protocol protocol) {
+ switch (protocol) {
+ case rtclog::IceCandidatePairConfig::UDP:
+ return IceCandidatePairProtocol::kUdp;
+ case rtclog::IceCandidatePairConfig::TCP:
+ return IceCandidatePairProtocol::kTcp;
+ case rtclog::IceCandidatePairConfig::SSLTCP:
+ return IceCandidatePairProtocol::kSsltcp;
+ case rtclog::IceCandidatePairConfig::TLS:
+ return IceCandidatePairProtocol::kTls;
+ case rtclog::IceCandidatePairConfig::UNKNOWN_PROTOCOL:
+ return IceCandidatePairProtocol::kUnknown;
+ }
+ RTC_NOTREACHED();
+ return IceCandidatePairProtocol::kUnknown;
+}
+
+IceCandidatePairAddressFamily GetRuntimeIceCandidatePairAddressFamily(
+ rtclog::IceCandidatePairConfig::AddressFamily address_family) {
+ switch (address_family) {
+ case rtclog::IceCandidatePairConfig::IPV4:
+ return IceCandidatePairAddressFamily::kIpv4;
+ case rtclog::IceCandidatePairConfig::IPV6:
+ return IceCandidatePairAddressFamily::kIpv6;
+ case rtclog::IceCandidatePairConfig::UNKNOWN_ADDRESS_FAMILY:
+ return IceCandidatePairAddressFamily::kUnknown;
+ }
+ RTC_NOTREACHED();
+ return IceCandidatePairAddressFamily::kUnknown;
+}
+
+IceCandidateNetworkType GetRuntimeIceCandidateNetworkType(
+ rtclog::IceCandidatePairConfig::NetworkType network_type) {
+ switch (network_type) {
+ case rtclog::IceCandidatePairConfig::ETHERNET:
+ return IceCandidateNetworkType::kEthernet;
+ case rtclog::IceCandidatePairConfig::LOOPBACK:
+ return IceCandidateNetworkType::kLoopback;
+ case rtclog::IceCandidatePairConfig::WIFI:
+ return IceCandidateNetworkType::kWifi;
+ case rtclog::IceCandidatePairConfig::VPN:
+ return IceCandidateNetworkType::kVpn;
+ case rtclog::IceCandidatePairConfig::CELLULAR:
+ return IceCandidateNetworkType::kCellular;
+ case rtclog::IceCandidatePairConfig::UNKNOWN_NETWORK_TYPE:
+ return IceCandidateNetworkType::kUnknown;
+ }
+ RTC_NOTREACHED();
+ return IceCandidateNetworkType::kUnknown;
+}
+
+IceCandidatePairEventType GetRuntimeIceCandidatePairEventType(
+ rtclog::IceCandidatePairEvent::IceCandidatePairEventType type) {
+ switch (type) {
+ case rtclog::IceCandidatePairEvent::CHECK_SENT:
+ return IceCandidatePairEventType::kCheckSent;
+ case rtclog::IceCandidatePairEvent::CHECK_RECEIVED:
+ return IceCandidatePairEventType::kCheckReceived;
+ case rtclog::IceCandidatePairEvent::CHECK_RESPONSE_SENT:
+ return IceCandidatePairEventType::kCheckResponseSent;
+ case rtclog::IceCandidatePairEvent::CHECK_RESPONSE_RECEIVED:
+ return IceCandidatePairEventType::kCheckResponseReceived;
+ }
+ RTC_NOTREACHED();
+ return IceCandidatePairEventType::kCheckSent;
+}
+
std::pair<uint64_t, bool> ParseVarInt(std::istream& stream) {
uint64_t varint = 0;
for (size_t bytes_read = 0; bytes_read < 10; ++bytes_read) {
@@ -670,6 +776,61 @@
return res;
}
+ParsedRtcEventLog::IceCandidatePairConfig
+ParsedRtcEventLog::GetIceCandidatePairConfig(size_t index) const {
+ RTC_CHECK_LT(index, GetNumberOfEvents());
+ const rtclog::Event& rtc_event = events_[index];
+ RTC_CHECK(rtc_event.has_type());
+ RTC_CHECK_EQ(rtc_event.type(), rtclog::Event::ICE_CANDIDATE_PAIR_CONFIG);
+ IceCandidatePairConfig res;
+ const rtclog::IceCandidatePairConfig& config =
+ rtc_event.ice_candidate_pair_config();
+ res.timestamp = GetTimestamp(index);
+ RTC_CHECK(config.has_config_type());
+ res.type = GetRuntimeIceCandidatePairConfigType(config.config_type());
+ RTC_CHECK(config.has_candidate_pair_id());
+ res.candidate_pair_id = config.candidate_pair_id();
+ RTC_CHECK(config.has_local_candidate_type());
+ res.local_candidate_type =
+ GetRuntimeIceCandidateType(config.local_candidate_type());
+ RTC_CHECK(config.has_local_relay_protocol());
+ res.local_relay_protocol =
+ GetRuntimeIceCandidatePairProtocol(config.local_relay_protocol());
+ RTC_CHECK(config.has_local_network_type());
+ res.local_network_type =
+ GetRuntimeIceCandidateNetworkType(config.local_network_type());
+ RTC_CHECK(config.has_local_address_family());
+ res.local_address_family =
+ GetRuntimeIceCandidatePairAddressFamily(config.local_address_family());
+ RTC_CHECK(config.has_remote_candidate_type());
+ res.remote_candidate_type =
+ GetRuntimeIceCandidateType(config.remote_candidate_type());
+ RTC_CHECK(config.has_remote_address_family());
+ res.remote_address_family =
+ GetRuntimeIceCandidatePairAddressFamily(config.remote_address_family());
+ RTC_CHECK(config.has_candidate_pair_protocol());
+ res.candidate_pair_protocol =
+ GetRuntimeIceCandidatePairProtocol(config.candidate_pair_protocol());
+ return res;
+}
+
+ParsedRtcEventLog::IceCandidatePairEvent
+ParsedRtcEventLog::GetIceCandidatePairEvent(size_t index) const {
+ RTC_CHECK_LT(index, GetNumberOfEvents());
+ const rtclog::Event& rtc_event = events_[index];
+ RTC_CHECK(rtc_event.has_type());
+ RTC_CHECK_EQ(rtc_event.type(), rtclog::Event::ICE_CANDIDATE_PAIR_EVENT);
+ IceCandidatePairEvent res;
+ const rtclog::IceCandidatePairEvent& event =
+ rtc_event.ice_candidate_pair_event();
+ res.timestamp = GetTimestamp(index);
+ RTC_CHECK(event.has_event_type());
+ res.type = GetRuntimeIceCandidatePairEventType(event.event_type());
+ RTC_CHECK(event.has_candidate_pair_id());
+ res.candidate_pair_id = event.candidate_pair_id();
+ return res;
+}
+
// Returns the MediaType for registered SSRCs. Search from the end to use last
// registered types first.
ParsedRtcEventLog::MediaType ParsedRtcEventLog::GetMediaType(
diff --git a/logging/rtc_event_log/rtc_event_log_parser.h b/logging/rtc_event_log/rtc_event_log_parser.h
index 6438918..d4488bc 100644
--- a/logging/rtc_event_log/rtc_event_log_parser.h
+++ b/logging/rtc_event_log/rtc_event_log_parser.h
@@ -17,6 +17,8 @@
#include "call/video_receive_stream.h"
#include "call/video_send_stream.h"
+#include "logging/rtc_event_log/events/rtc_event_ice_candidate_pair.h"
+#include "logging/rtc_event_log/events/rtc_event_ice_candidate_pair_config.h"
#include "logging/rtc_event_log/events/rtc_event_probe_result_failure.h"
#include "logging/rtc_event_log/rtc_event_log.h"
#include "logging/rtc_event_log/rtc_stream_config.h"
@@ -70,6 +72,25 @@
bool in_alr;
};
+ struct IceCandidatePairConfig {
+ uint64_t timestamp;
+ IceCandidatePairEventType type;
+ uint32_t candidate_pair_id;
+ IceCandidateType local_candidate_type;
+ IceCandidatePairProtocol local_relay_protocol;
+ IceCandidateNetworkType local_network_type;
+ IceCandidatePairAddressFamily local_address_family;
+ IceCandidateType remote_candidate_type;
+ IceCandidatePairAddressFamily remote_address_family;
+ IceCandidatePairProtocol candidate_pair_protocol;
+ };
+
+ struct IceCandidatePairEvent {
+ uint64_t timestamp;
+ IceCandidatePairEventType type;
+ uint32_t candidate_pair_id;
+ };
+
enum EventType {
UNKNOWN_EVENT = 0,
LOG_START = 1,
@@ -86,7 +107,9 @@
AUDIO_NETWORK_ADAPTATION_EVENT = 16,
BWE_PROBE_CLUSTER_CREATED_EVENT = 17,
BWE_PROBE_RESULT_EVENT = 18,
- ALR_STATE_EVENT = 19
+ ALR_STATE_EVENT = 19,
+ ICE_CANDIDATE_PAIR_CONFIG = 20,
+ ICE_CANDIDATE_PAIR_EVENT = 21,
};
enum class MediaType { ANY, AUDIO, VIDEO, DATA };
@@ -188,6 +211,9 @@
AlrStateEvent GetAlrState(size_t index) const;
+ IceCandidatePairConfig GetIceCandidatePairConfig(size_t index) const;
+ IceCandidatePairEvent GetIceCandidatePairEvent(size_t index) const;
+
private:
rtclog::StreamConfig GetVideoReceiveConfig(const rtclog::Event& event) const;
std::vector<rtclog::StreamConfig> GetVideoSendConfig(
diff --git a/rtc_tools/event_log_visualizer/analyzer.cc b/rtc_tools/event_log_visualizer/analyzer.cc
index 3c6a074..2bbb09c 100644
--- a/rtc_tools/event_log_visualizer/analyzer.cc
+++ b/rtc_tools/event_log_visualizer/analyzer.cc
@@ -62,6 +62,8 @@
namespace {
+const int kNumMicrosecsPerSec = 1000000;
+
void SortPacketFeedbackVector(std::vector<PacketFeedback>* vec) {
auto pred = [](const PacketFeedback& packet_feedback) {
return packet_feedback.arrival_time_ms == PacketFeedback::kNotReceived;
@@ -88,9 +90,10 @@
double AbsSendTimeToMicroseconds(int64_t abs_send_time) {
// The timestamp is a fixed point representation with 6 bits for seconds
// and 18 bits for fractions of a second. Thus, we divide by 2^18 to get the
- // time in seconds and then multiply by 1000000 to convert to microseconds.
+ // time in seconds and then multiply by kNumMicrosecsPerSec to convert to
+ // microseconds.
static constexpr double kTimestampToMicroSec =
- 1000000.0 / static_cast<double>(1ul << 18);
+ static_cast<double>(kNumMicrosecsPerSec) / static_cast<double>(1ul << 18);
return abs_send_time * kTimestampToMicroSec;
}
@@ -193,7 +196,9 @@
RTC_LOG(LS_WARNING) << "New capture time " << new_packet.header.timestamp
<< ", received time " << new_packet.timestamp;
RTC_LOG(LS_WARNING) << "Receive time difference " << recv_time_diff << " = "
- << static_cast<double>(recv_time_diff) / 1000000 << "s";
+ << static_cast<double>(recv_time_diff) /
+ kNumMicrosecsPerSec
+ << "s";
RTC_LOG(LS_WARNING) << "Send time difference " << send_time_diff << " = "
<< static_cast<double>(send_time_diff) /
kVideoSampleRate
@@ -211,7 +216,8 @@
uint64_t begin_time,
TimeSeries* result) {
for (size_t i = 0; i < data.size(); i++) {
- float x = static_cast<float>(data[i].timestamp - begin_time) / 1000000;
+ float x = static_cast<float>(data[i].timestamp - begin_time) /
+ kNumMicrosecsPerSec;
rtc::Optional<float> y = get_y(data[i]);
if (y)
result->points.emplace_back(x, *y);
@@ -229,7 +235,8 @@
uint64_t begin_time,
TimeSeries* result) {
for (size_t i = 1; i < data.size(); i++) {
- float x = static_cast<float>(data[i].timestamp - begin_time) / 1000000;
+ float x = static_cast<float>(data[i].timestamp - begin_time) /
+ kNumMicrosecsPerSec;
rtc::Optional<ResultType> y = get_y(data[i - 1], data[i]);
if (y)
result->points.emplace_back(x, static_cast<float>(*y));
@@ -246,7 +253,8 @@
TimeSeries* result) {
ResultType sum = 0;
for (size_t i = 0; i < data.size(); i++) {
- float x = static_cast<float>(data[i].timestamp - begin_time) / 1000000;
+ float x = static_cast<float>(data[i].timestamp - begin_time) /
+ kNumMicrosecsPerSec;
rtc::Optional<ResultType> y = extract(data[i]);
if (y) {
sum += *y;
@@ -267,7 +275,8 @@
TimeSeries* result) {
ResultType sum = 0;
for (size_t i = 1; i < data.size(); i++) {
- float x = static_cast<float>(data[i].timestamp - begin_time) / 1000000;
+ float x = static_cast<float>(data[i].timestamp - begin_time) /
+ kNumMicrosecsPerSec;
rtc::Optional<ResultType> y = extract(data[i - 1], data[i]);
if (y)
sum += *y;
@@ -307,13 +316,118 @@
sum_in_window -= *value;
++window_index_begin;
}
- float window_duration_s = static_cast<float>(window_duration_us) / 1000000;
- float x = static_cast<float>(t - begin_time) / 1000000;
+ float window_duration_s =
+ static_cast<float>(window_duration_us) / kNumMicrosecsPerSec;
+ float x = static_cast<float>(t - begin_time) / kNumMicrosecsPerSec;
float y = sum_in_window / window_duration_s;
result->points.emplace_back(x, y);
}
}
+const char kUnknownEnumValue[] = "unknown";
+
+const char kIceCandidateTypeLocal[] = "local";
+const char kIceCandidateTypeStun[] = "stun";
+const char kIceCandidateTypePrflx[] = "prflx";
+const char kIceCandidateTypeRelay[] = "relay";
+
+const char kProtocolUdp[] = "udp";
+const char kProtocolTcp[] = "tcp";
+const char kProtocolSsltcp[] = "ssltcp";
+const char kProtocolTls[] = "tls";
+
+const char kAddressFamilyIpv4[] = "ipv4";
+const char kAddressFamilyIpv6[] = "ipv6";
+
+const char kNetworkTypeEthernet[] = "ethernet";
+const char kNetworkTypeLoopback[] = "loopback";
+const char kNetworkTypeWifi[] = "wifi";
+const char kNetworkTypeVpn[] = "vpn";
+const char kNetworkTypeCellular[] = "cellular";
+
+std::string GetIceCandidateTypeAsString(webrtc::IceCandidateType type) {
+ switch (type) {
+ case webrtc::IceCandidateType::kLocal:
+ return kIceCandidateTypeLocal;
+ case webrtc::IceCandidateType::kStun:
+ return kIceCandidateTypeStun;
+ case webrtc::IceCandidateType::kPrflx:
+ return kIceCandidateTypePrflx;
+ case webrtc::IceCandidateType::kRelay:
+ return kIceCandidateTypeRelay;
+ default:
+ return kUnknownEnumValue;
+ }
+}
+
+std::string GetProtocolAsString(webrtc::IceCandidatePairProtocol protocol) {
+ switch (protocol) {
+ case webrtc::IceCandidatePairProtocol::kUdp:
+ return kProtocolUdp;
+ case webrtc::IceCandidatePairProtocol::kTcp:
+ return kProtocolTcp;
+ case webrtc::IceCandidatePairProtocol::kSsltcp:
+ return kProtocolSsltcp;
+ case webrtc::IceCandidatePairProtocol::kTls:
+ return kProtocolTls;
+ default:
+ return kUnknownEnumValue;
+ }
+}
+
+std::string GetAddressFamilyAsString(
+ webrtc::IceCandidatePairAddressFamily family) {
+ switch (family) {
+ case webrtc::IceCandidatePairAddressFamily::kIpv4:
+ return kAddressFamilyIpv4;
+ case webrtc::IceCandidatePairAddressFamily::kIpv6:
+ return kAddressFamilyIpv6;
+ default:
+ return kUnknownEnumValue;
+ }
+}
+
+std::string GetNetworkTypeAsString(webrtc::IceCandidateNetworkType type) {
+ switch (type) {
+ case webrtc::IceCandidateNetworkType::kEthernet:
+ return kNetworkTypeEthernet;
+ case webrtc::IceCandidateNetworkType::kLoopback:
+ return kNetworkTypeLoopback;
+ case webrtc::IceCandidateNetworkType::kWifi:
+ return kNetworkTypeWifi;
+ case webrtc::IceCandidateNetworkType::kVpn:
+ return kNetworkTypeVpn;
+ case webrtc::IceCandidateNetworkType::kCellular:
+ return kNetworkTypeCellular;
+ default:
+ return kUnknownEnumValue;
+ }
+}
+
+std::string GetCandidatePairLogDescriptionAsString(
+ const ParsedRtcEventLog::IceCandidatePairConfig& config) {
+ // Example: stun:wifi->relay(tcp):cellular@udp:ipv4
+ // represents a pair of a local server-reflexive candidate on a WiFi network
+ // and a remote relay candidate using TCP as the relay protocol on a cell
+ // network, when the candidate pair communicates over UDP using IPv4.
+ std::stringstream ss;
+ std::string local_candidate_type =
+ GetIceCandidateTypeAsString(config.local_candidate_type);
+ std::string remote_candidate_type =
+ GetIceCandidateTypeAsString(config.remote_candidate_type);
+ if (config.local_candidate_type == webrtc::IceCandidateType::kRelay) {
+ local_candidate_type +=
+ "(" + GetProtocolAsString(config.local_relay_protocol) + ")";
+ }
+ ss << local_candidate_type << ":"
+ << GetNetworkTypeAsString(config.local_network_type) << ":"
+ << GetAddressFamilyAsString(config.local_address_family) << "->"
+ << remote_candidate_type << ":"
+ << GetAddressFamilyAsString(config.remote_address_family) << "@"
+ << GetProtocolAsString(config.candidate_pair_protocol);
+ return ss.str();
+}
+
} // namespace
EventLogAnalyzer::EventLogAnalyzer(const ParsedRtcEventLog& log)
@@ -526,6 +640,16 @@
alr_state_events_.push_back(parsed_log_.GetAlrState(i));
break;
}
+ case ParsedRtcEventLog::ICE_CANDIDATE_PAIR_CONFIG: {
+ ice_candidate_pair_configs_.push_back(
+ parsed_log_.GetIceCandidatePairConfig(i));
+ break;
+ }
+ case ParsedRtcEventLog::ICE_CANDIDATE_PAIR_EVENT: {
+ ice_candidate_pair_events_.push_back(
+ parsed_log_.GetIceCandidatePairEvent(i));
+ break;
+ }
case ParsedRtcEventLog::UNKNOWN_EVENT: {
break;
}
@@ -538,7 +662,7 @@
}
begin_time_ = first_timestamp;
end_time_ = last_timestamp;
- call_duration_s_ = static_cast<float>(end_time_ - begin_time_) / 1000000;
+ call_duration_s_ = ToCallTime(end_time_);
if (last_log_start) {
// The log was missing the last LOG_END event. Fake it.
log_segments_.push_back(std::make_pair(*last_log_start, end_time_));
@@ -625,7 +749,7 @@
last_rtp_timestamp = unwrapper.Unwrap(packets[i].header.timestamp);
last_log_timestamp = packets[i].timestamp;
}
- if (last_log_timestamp - first_log_timestamp < 1000000) {
+ if (last_log_timestamp - first_log_timestamp < kNumMicrosecsPerSec) {
RTC_LOG(LS_WARNING)
<< "Failed to estimate RTP clock frequency: Stream too short. ("
<< packets.size() << " packets, "
@@ -633,7 +757,8 @@
return rtc::nullopt;
}
double duration =
- static_cast<double>(last_log_timestamp - first_log_timestamp) / 1000000;
+ static_cast<double>(last_log_timestamp - first_log_timestamp) /
+ kNumMicrosecsPerSec;
double estimated_frequency =
(last_rtp_timestamp - first_rtp_timestamp) / duration;
for (uint32_t f : {8000, 16000, 32000, 48000, 90000}) {
@@ -648,7 +773,7 @@
}
float EventLogAnalyzer::ToCallTime(int64_t timestamp) const {
- return static_cast<float>(timestamp - begin_time_) / 1000000;
+ return static_cast<float>(timestamp - begin_time_) / kNumMicrosecsPerSec;
}
void EventLogAnalyzer::CreatePacketGraph(PacketDirection desired_direction,
@@ -699,8 +824,7 @@
std::string label = label_prefix + " " + GetStreamName(stream_id);
TimeSeries time_series(label, LineStyle::kStep);
for (size_t i = 0; i < packet_stream.size(); i++) {
- float x = static_cast<float>(packet_stream[i].timestamp - begin_time_) /
- 1000000;
+ float x = ToCallTime(packet_stream[i].timestamp);
time_series.points.emplace_back(x, i + 1);
}
@@ -738,7 +862,7 @@
parsed_log_.GetAudioPlayout(i, &ssrc);
uint64_t timestamp = parsed_log_.GetTimestamp(i);
if (MatchingSsrc(ssrc, desired_ssrc_)) {
- float x = static_cast<float>(timestamp - begin_time_) / 1000000;
+ float x = ToCallTime(timestamp);
float y = static_cast<float>(timestamp - last_playout[ssrc]) / 1000;
if (time_series[ssrc].points.size() == 0) {
// There were no previusly logged playout for this SSRC.
@@ -776,7 +900,7 @@
// streams. Tracking bug: webrtc:6399
for (auto& packet : packet_stream) {
if (packet.header.extension.hasAudioLevel) {
- float x = static_cast<float>(packet.timestamp - begin_time_) / 1000000;
+ float x = ToCallTime(packet.timestamp);
// The audio level is stored in -dBov (so e.g. -10 dBov is stored as 10)
// Here we convert it to dBov.
float y = static_cast<float>(-packet.header.extension.audioLevel);
@@ -867,7 +991,7 @@
std::max(highest_prior_seq_number, sequence_number);
++window_index_begin;
}
- float x = static_cast<float>(t - begin_time_) / 1000000;
+ float x = ToCallTime(t);
int64_t expected_packets = highest_seq_number - highest_prior_seq_number;
if (expected_packets > 0) {
int64_t received_packets = window_index_end - window_index_begin;
@@ -956,7 +1080,7 @@
TimeSeries time_series("Fraction lost", LineStyle::kLine,
PointStyle::kHighlight);
for (auto& bwe_update : bwe_loss_updates_) {
- float x = static_cast<float>(bwe_update.timestamp - begin_time_) / 1000000;
+ float x = ToCallTime(bwe_update.timestamp);
float y = static_cast<float>(bwe_update.fraction_loss) / 255 * 100;
time_series.points.emplace_back(x, y);
}
@@ -1016,8 +1140,8 @@
++window_index_begin;
}
float window_duration_in_seconds =
- static_cast<float>(window_duration_) / 1000000;
- float x = static_cast<float>(time - begin_time_) / 1000000;
+ static_cast<float>(window_duration_) / kNumMicrosecsPerSec;
+ float x = ToCallTime(time);
float y = bytes_in_window * 8 / window_duration_in_seconds / 1000;
bitrate_series.points.emplace_back(x, y);
}
@@ -1027,8 +1151,7 @@
if (desired_direction == kOutgoingPacket) {
TimeSeries loss_series("Loss-based estimate", LineStyle::kStep);
for (auto& loss_update : bwe_loss_updates_) {
- float x =
- static_cast<float>(loss_update.timestamp - begin_time_) / 1000000;
+ float x = ToCallTime(loss_update.timestamp);
float y = static_cast<float>(loss_update.new_bitrate) / 1000;
loss_series.points.emplace_back(x, y);
}
@@ -1046,8 +1169,7 @@
BandwidthUsage last_detector_state = BandwidthUsage::kBwNormal;
for (auto& delay_update : bwe_delay_updates_) {
- float x =
- static_cast<float>(delay_update.timestamp - begin_time_) / 1000000;
+ float x = ToCallTime(delay_update.timestamp);
float y = static_cast<float>(delay_update.bitrate_bps) / 1000;
if (last_detector_state != delay_update.detector_state) {
@@ -1079,7 +1201,7 @@
TimeSeries created_series("Probe cluster created.", LineStyle::kNone,
PointStyle::kHighlight);
for (auto& cluster : bwe_probe_cluster_created_events_) {
- float x = static_cast<float>(cluster.timestamp - begin_time_) / 1000000;
+ float x = ToCallTime(cluster.timestamp);
float y = static_cast<float>(cluster.bitrate_bps) / 1000;
created_series.points.emplace_back(x, y);
}
@@ -1088,7 +1210,7 @@
PointStyle::kHighlight);
for (auto& result : bwe_probe_result_events_) {
if (result.bitrate_bps) {
- float x = static_cast<float>(result.timestamp - begin_time_) / 1000000;
+ float x = ToCallTime(result.timestamp);
float y = static_cast<float>(*result.bitrate_bps) / 1000;
result_series.points.emplace_back(x, y);
}
@@ -1150,7 +1272,7 @@
for (const auto& kv : remb_packets) {
const LoggedRtcpPacket* const rtcp = kv.second;
const rtcp::Remb* const remb = static_cast<rtcp::Remb*>(rtcp->packet.get());
- float x = static_cast<float>(rtcp->timestamp - begin_time_) / 1000000;
+ float x = ToCallTime(rtcp->timestamp);
float y = static_cast<float>(remb->bitrate_bps()) / 1000;
remb_series.points.emplace_back(x, y);
}
@@ -1290,8 +1412,7 @@
acked_bitrate.Update(packet.payload_size, packet.arrival_time_ms);
bitrate_bps = acked_bitrate.Rate(feedback.back().arrival_time_ms);
}
- float x = static_cast<float>(clock.TimeInMicroseconds() - begin_time_) /
- 1000000;
+ float x = ToCallTime(clock.TimeInMicroseconds());
float y = bitrate_bps.value_or(0) / 1000;
acked_time_series.points.emplace_back(x, y);
#if !(BWE_TEST_LOGGING_COMPILE_TIME_ENABLE)
@@ -1322,8 +1443,7 @@
if (observer.GetAndResetBitrateUpdated() ||
time_us - last_update_us >= 1e6) {
uint32_t y = observer.last_bitrate_bps() / 1000;
- float x = static_cast<float>(clock.TimeInMicroseconds() - begin_time_) /
- 1000000;
+ float x = ToCallTime(clock.TimeInMicroseconds());
time_series.points.emplace_back(x, y);
last_update_us = time_us;
}
@@ -1396,15 +1516,13 @@
rtc::Optional<uint32_t> bitrate_bps = acked_bitrate.Rate(arrival_time_ms);
if (bitrate_bps) {
uint32_t y = *bitrate_bps / 1000;
- float x = static_cast<float>(clock.TimeInMicroseconds() - begin_time_) /
- 1000000;
+ float x = ToCallTime(clock.TimeInMicroseconds());
acked_time_series.points.emplace_back(x, y);
}
if (packet_router.GetAndResetBitrateUpdated() ||
clock.TimeInMicroseconds() - last_update_us >= 1e6) {
uint32_t y = packet_router.last_bitrate_bps() / 1000;
- float x = static_cast<float>(clock.TimeInMicroseconds() - begin_time_) /
- 1000000;
+ float x = ToCallTime(clock.TimeInMicroseconds());
time_series.points.emplace_back(x, y);
last_update_us = clock.TimeInMicroseconds();
}
@@ -1475,9 +1593,7 @@
feedback_adapter.GetTransportFeedbackVector();
SortPacketFeedbackVector(&feedback);
for (const PacketFeedback& packet : feedback) {
- float x =
- static_cast<float>(clock.TimeInMicroseconds() - begin_time_) /
- 1000000;
+ float x = ToCallTime(clock.TimeInMicroseconds());
if (packet.send_time_ms == PacketFeedback::kNoSendTime) {
late_feedback_series.points.emplace_back(x, prev_y);
continue;
@@ -1587,7 +1703,7 @@
*estimated_frequency * 1000;
double send_time_ms =
static_cast<double>(packet.timestamp - first_send_timestamp) / 1000;
- float x = static_cast<float>(packet.timestamp - begin_time_) / 1000000;
+ float x = ToCallTime(packet.timestamp);
float y = send_time_ms - capture_time_ms;
pacer_delay_series.points.emplace_back(x, y);
}
@@ -1609,7 +1725,7 @@
TimeSeries timestamp_data(GetStreamName(stream_id) + " capture-time",
LineStyle::kLine, PointStyle::kHighlight);
for (LoggedRtpPacket packet : rtp_packets) {
- float x = static_cast<float>(packet.timestamp - begin_time_) / 1000000;
+ float x = ToCallTime(packet.timestamp);
float y = packet.header.timestamp;
timestamp_data.points.emplace_back(x, y);
}
@@ -1628,7 +1744,7 @@
continue;
rtcp::SenderReport* sr;
sr = static_cast<rtcp::SenderReport*>(rtcp.packet.get());
- float x = static_cast<float>(rtcp.timestamp - begin_time_) / 1000000;
+ float x = ToCallTime(rtcp.timestamp);
float y = sr->rtp_timestamp();
timestamp_data.points.emplace_back(x, y);
}
@@ -1986,6 +2102,81 @@
plot->SetTitle("NetEq timing");
}
+void EventLogAnalyzer::CreateIceCandidatePairConfigGraph(Plot* plot) {
+ std::map<uint32_t, TimeSeries> configs_by_cp_id;
+ for (const auto& config : ice_candidate_pair_configs_) {
+ if (configs_by_cp_id.find(config.candidate_pair_id) ==
+ configs_by_cp_id.end()) {
+ const std::string candidate_pair_desc =
+ GetCandidatePairLogDescriptionAsString(config);
+ configs_by_cp_id[config.candidate_pair_id] = TimeSeries(
+ candidate_pair_desc, LineStyle::kNone, PointStyle::kHighlight);
+ candidate_pair_desc_by_id_[config.candidate_pair_id] =
+ candidate_pair_desc;
+ }
+ float x = ToCallTime(config.timestamp);
+ float y = static_cast<float>(config.type);
+ configs_by_cp_id[config.candidate_pair_id].points.emplace_back(x, y);
+ }
+
+ // TODO(qingsi): There can be a large number of candidate pairs generated by
+ // certain calls and the frontend cannot render the chart in this case due to
+ // the failure of generating a palette with the same number of colors.
+ for (auto& kv : configs_by_cp_id) {
+ plot->AppendTimeSeries(std::move(kv.second));
+ }
+
+ plot->SetXAxis(0, call_duration_s_, "Time (s)", kLeftMargin, kRightMargin);
+ plot->SetSuggestedYAxis(0, 3, "Numeric Config Type", kBottomMargin,
+ kTopMargin);
+ plot->SetTitle("[IceEventLog] ICE candidate pair configs");
+}
+
+std::string EventLogAnalyzer::GetCandidatePairLogDescriptionFromId(
+ uint32_t candidate_pair_id) {
+ if (candidate_pair_desc_by_id_.find(candidate_pair_id) !=
+ candidate_pair_desc_by_id_.end()) {
+ return candidate_pair_desc_by_id_[candidate_pair_id];
+ }
+ for (const auto& config : ice_candidate_pair_configs_) {
+ // TODO(qingsi): Add the handling of the "Updated" config event after the
+ // visualization of property change for candidate pairs is introduced.
+ if (candidate_pair_desc_by_id_.find(config.candidate_pair_id) ==
+ candidate_pair_desc_by_id_.end()) {
+ const std::string candidate_pair_desc =
+ GetCandidatePairLogDescriptionAsString(config);
+ candidate_pair_desc_by_id_[config.candidate_pair_id] =
+ candidate_pair_desc;
+ }
+ }
+ return candidate_pair_desc_by_id_[candidate_pair_id];
+}
+
+void EventLogAnalyzer::CreateIceConnectivityCheckGraph(Plot* plot) {
+ std::map<uint32_t, TimeSeries> checks_by_cp_id;
+ for (const auto& event : ice_candidate_pair_events_) {
+ if (checks_by_cp_id.find(event.candidate_pair_id) ==
+ checks_by_cp_id.end()) {
+ checks_by_cp_id[event.candidate_pair_id] = TimeSeries(
+ GetCandidatePairLogDescriptionFromId(event.candidate_pair_id),
+ LineStyle::kNone, PointStyle::kHighlight);
+ }
+ float x = ToCallTime(event.timestamp);
+ float y = static_cast<float>(event.type);
+ checks_by_cp_id[event.candidate_pair_id].points.emplace_back(x, y);
+ }
+
+ // TODO(qingsi): The same issue as in CreateIceCandidatePairConfigGraph.
+ for (auto& kv : checks_by_cp_id) {
+ plot->AppendTimeSeries(std::move(kv.second));
+ }
+
+ plot->SetXAxis(0, call_duration_s_, "Time (s)", kLeftMargin, kRightMargin);
+ plot->SetSuggestedYAxis(0, 4, "Numeric Connectivity State", kBottomMargin,
+ kTopMargin);
+ plot->SetTitle("[IceEventLog] ICE connectivity checks");
+}
+
void EventLogAnalyzer::Notification(
std::unique_ptr<TriageNotification> notification) {
notifications_.push_back(std::move(notification));
diff --git a/rtc_tools/event_log_visualizer/analyzer.h b/rtc_tools/event_log_visualizer/analyzer.h
index 5d0faab..fafce66 100644
--- a/rtc_tools/event_log_visualizer/analyzer.h
+++ b/rtc_tools/event_log_visualizer/analyzer.h
@@ -109,6 +109,9 @@
int file_sample_rate_hz,
Plot* plot);
+ void CreateIceCandidatePairConfigGraph(Plot* plot);
+ void CreateIceConnectivityCheckGraph(Plot* plot);
+
// Returns a vector of capture and arrival timestamps for the video frames
// of the stream with the most number of frames.
std::vector<std::pair<int64_t, int64_t>> GetFrameTimestamps() const;
@@ -159,6 +162,8 @@
void Notification(std::unique_ptr<TriageNotification> notification);
+ std::string GetCandidatePairLogDescriptionFromId(uint32_t candidate_pair_id);
+
const ParsedRtcEventLog& parsed_log_;
// A list of SSRCs we are interested in analysing.
@@ -204,6 +209,14 @@
std::vector<ParsedRtcEventLog::AlrStateEvent> alr_state_events_;
+ std::vector<ParsedRtcEventLog::IceCandidatePairConfig>
+ ice_candidate_pair_configs_;
+
+ std::vector<ParsedRtcEventLog::IceCandidatePairEvent>
+ ice_candidate_pair_events_;
+
+ std::map<uint32_t, std::string> candidate_pair_desc_by_id_;
+
// Window and step size used for calculating moving averages, e.g. bitrate.
// The generated data points will be |step_| microseconds apart.
// Only events occuring at most |window_duration_| microseconds before the
diff --git a/rtc_tools/event_log_visualizer/main.cc b/rtc_tools/event_log_visualizer/main.cc
index 4a6ec64..2e7a79e 100644
--- a/rtc_tools/event_log_visualizer/main.cc
+++ b/rtc_tools/event_log_visualizer/main.cc
@@ -115,6 +115,12 @@
DEFINE_bool(plot_audio_jitter_buffer,
false,
"Plot the audio jitter buffer delay profile.");
+DEFINE_bool(plot_ice_candidate_pair_config,
+ false,
+ "Plot the ICE candidate pair config events.");
+DEFINE_bool(plot_ice_connectivity_check,
+ false,
+ "Plot the ICE candidate pair connectivity checks.");
DEFINE_string(
force_fieldtrials,
@@ -318,6 +324,13 @@
collection->AppendNewPlot());
}
+ if (FLAG_plot_ice_candidate_pair_config) {
+ analyzer.CreateIceCandidatePairConfigGraph(collection->AppendNewPlot());
+ }
+ if (FLAG_plot_ice_connectivity_check) {
+ analyzer.CreateIceConnectivityCheckGraph(collection->AppendNewPlot());
+ }
+
collection->Draw();
if (FLAG_print_triage_notifications) {
@@ -356,4 +369,6 @@
FLAG_plot_audio_encoder_dtx = setting;
FLAG_plot_audio_encoder_num_channels = setting;
FLAG_plot_audio_jitter_buffer = setting;
+ FLAG_plot_ice_candidate_pair_config = setting;
+ FLAG_plot_ice_connectivity_check = setting;
}