Revert "Create new API for RtcEventLogParser."
This reverts commit 9e336ec0b8a77c3461d13677cff3563c11c88daa.
Reason for revert: Code can accidentally include the deprecated parser but link with the new one, or vice versa. Reverting to fix naming.
Original change's description:
> Create new API for RtcEventLogParser.
>
> The new API stores events gathered by event type. For example, it is
> possible to ask fo a list of all incoming RTCP messages or all audio
> playout events.
>
> The new API is experimental and may change over next few weeks. Once
> it has stabilized and all unit tests and existing tools have been
> ported to the new API, the old one will be removed.
>
> This CL also updates the event_log_visualizer tool to use the new
> parser API. This is not a funcional change except for:
> - Incoming and outgoing audio level are now drawn in two separate plots.
> - Incoming and outgoing timstamps are now drawn in two separate plots.
> - RTCP count is no longer split into Video and Audio. It also counts
> all RTCP packets rather than only specific message types.
> - Slight timing difference in sendside BWE simulation due to only
> iterating over transport feedbacks and not over all RTCP packets.
> This timing changes are not visible in the plots.
>
>
> Media type for RTCP messages might not be identified correctly by
> rtc_event_log2text anymore. On the other hand, assigning a specific
> media type to an RTCP packet was a bit hacky to begin with.
>
> Bug: webrtc:8111
> Change-Id: I8e7168302beb69b2e163a097a2a142b86dd4a26b
> Reviewed-on: https://webrtc-review.googlesource.com/60865
> Reviewed-by: Minyue Li <minyue@webrtc.org>
> Reviewed-by: Sebastian Jansson <srte@webrtc.org>
> Commit-Queue: Björn Terelius <terelius@webrtc.org>
> Cr-Commit-Position: refs/heads/master@{#23015}
TBR=terelius@webrtc.org,srte@webrtc.org,minyue@webrtc.org
Change-Id: Ib4bbcf0563423675a3cc1dce59ebf665e0c5dae9
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: webrtc:8111
Reviewed-on: https://webrtc-review.googlesource.com/72500
Reviewed-by: Björn Terelius <terelius@webrtc.org>
Commit-Queue: Björn Terelius <terelius@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#23026}
diff --git a/logging/BUILD.gn b/logging/BUILD.gn
index 8f81e7a..a47c81d 100644
--- a/logging/BUILD.gn
+++ b/logging/BUILD.gn
@@ -253,8 +253,8 @@
rtc_static_library("rtc_event_log_parser") {
sources = [
- "rtc_event_log/rtc_event_log_parser2.cc",
- "rtc_event_log/rtc_event_log_parser2.h",
+ "rtc_event_log/rtc_event_log_parser.cc",
+ "rtc_event_log/rtc_event_log_parser.h",
]
deps = [
@@ -265,7 +265,6 @@
":rtc_event_log_proto",
":rtc_stream_config",
"..:webrtc_common",
- "../api:libjingle_peerconnection_api",
"../call:video_stream_api",
"../modules/audio_coding:audio_network_adaptor",
"../modules/remote_bitrate_estimator:remote_bitrate_estimator",
@@ -366,7 +365,6 @@
"../rtc_base:checks",
"../rtc_base:protobuf_utils",
"../rtc_base:rtc_base_approved",
- "../rtc_base:stringutils",
# TODO(kwiberg): Remove this dependency.
"../api/audio_codecs:audio_codecs_api",
diff --git a/logging/rtc_event_log/encoder/rtc_event_log_encoder_unittest.cc b/logging/rtc_event_log/encoder/rtc_event_log_encoder_unittest.cc
index 0e6e183..6d88298 100644
--- a/logging/rtc_event_log/encoder/rtc_event_log_encoder_unittest.cc
+++ b/logging/rtc_event_log/encoder/rtc_event_log_encoder_unittest.cc
@@ -32,7 +32,7 @@
#include "logging/rtc_event_log/events/rtc_event_rtp_packet_outgoing.h"
#include "logging/rtc_event_log/events/rtc_event_video_receive_stream_config.h"
#include "logging/rtc_event_log/events/rtc_event_video_send_stream_config.h"
-#include "logging/rtc_event_log/rtc_event_log_parser2.h"
+#include "logging/rtc_event_log/rtc_event_log_parser.h"
#include "modules/audio_coding/audio_network_adaptor/include/audio_network_adaptor_config.h"
#include "modules/remote_bitrate_estimator/include/bwe_defines.h"
#include "modules/rtp_rtcp/source/rtcp_packet/bye.h" // Arbitrary RTCP message.
@@ -142,11 +142,11 @@
ASSERT_EQ(parsed_log_.GetEventType(0),
ParsedRtcEventLog::AUDIO_NETWORK_ADAPTATION_EVENT);
- LoggedAudioNetworkAdaptationEvent parsed_event =
- parsed_log_.GetAudioNetworkAdaptation(0);
+ AudioEncoderRuntimeConfig parsed_runtime_config;
+ parsed_log_.GetAudioNetworkAdaptation(0, &parsed_runtime_config);
- EXPECT_EQ(parsed_event.timestamp_us, timestamp_us);
- EXPECT_EQ(parsed_event.config, original_runtime_config);
+ EXPECT_EQ(parsed_log_.GetTimestamp(0), timestamp_us);
+ EXPECT_EQ(parsed_runtime_config, original_runtime_config);
}
TEST_P(RtcEventLogEncoderTest, RtcEventAudioNetworkAdaptationBitrate) {
@@ -234,10 +234,11 @@
ASSERT_EQ(parsed_log_.GetEventType(0),
ParsedRtcEventLog::AUDIO_PLAYOUT_EVENT);
- LoggedAudioPlayoutEvent playout_event = parsed_log_.GetAudioPlayout(0);
+ uint32_t parsed_ssrc;
+ parsed_log_.GetAudioPlayout(0, &parsed_ssrc);
- EXPECT_EQ(playout_event.timestamp_us, timestamp_us);
- EXPECT_EQ(playout_event.ssrc, ssrc);
+ EXPECT_EQ(parsed_log_.GetTimestamp(0), timestamp_us);
+ EXPECT_EQ(parsed_ssrc, ssrc);
}
TEST_P(RtcEventLogEncoderTest, RtcEventAudioReceiveStreamConfig) {
@@ -332,12 +333,16 @@
ASSERT_EQ(parsed_log_.GetEventType(0),
ParsedRtcEventLog::LOSS_BASED_BWE_UPDATE);
- LoggedBweLossBasedUpdate bwe_update = parsed_log_.GetLossBasedBweUpdate(0);
+ int32_t parsed_bitrate_bps;
+ uint8_t parsed_fraction_loss;
+ int32_t parsed_total_packets;
+ parsed_log_.GetLossBasedBweUpdate(
+ 0, &parsed_bitrate_bps, &parsed_fraction_loss, &parsed_total_packets);
- EXPECT_EQ(bwe_update.timestamp_us, timestamp_us);
- EXPECT_EQ(bwe_update.bitrate_bps, bitrate_bps);
- EXPECT_EQ(bwe_update.fraction_lost, fraction_loss);
- EXPECT_EQ(bwe_update.expected_packets, total_packets);
+ EXPECT_EQ(parsed_log_.GetTimestamp(0), timestamp_us);
+ EXPECT_EQ(parsed_bitrate_bps, bitrate_bps);
+ EXPECT_EQ(parsed_fraction_loss, fraction_loss);
+ EXPECT_EQ(parsed_total_packets, total_packets);
}
TEST_P(RtcEventLogEncoderTest, RtcEventLoggingStarted) {
diff --git a/logging/rtc_event_log/rtc_event_log.h b/logging/rtc_event_log/rtc_event_log.h
index 0c71406..a0714e0 100644
--- a/logging/rtc_event_log/rtc_event_log.h
+++ b/logging/rtc_event_log/rtc_event_log.h
@@ -21,7 +21,6 @@
namespace webrtc {
-// TODO(terelius): Move this to the parser.
enum PacketDirection { kIncomingPacket = 0, kOutgoingPacket };
class RtcEventLog {
diff --git a/logging/rtc_event_log/rtc_event_log2rtp_dump.cc b/logging/rtc_event_log/rtc_event_log2rtp_dump.cc
index c4d6948..c6fa129 100644
--- a/logging/rtc_event_log/rtc_event_log2rtp_dump.cc
+++ b/logging/rtc_event_log/rtc_event_log2rtp_dump.cc
@@ -16,7 +16,7 @@
#include <string>
#include "logging/rtc_event_log/rtc_event_log.h"
-#include "logging/rtc_event_log/rtc_event_log_parser2.h"
+#include "logging/rtc_event_log/rtc_event_log_parser.h"
#include "modules/rtp_rtcp/source/byte_io.h"
#include "modules/rtp_rtcp/source/rtp_utility.h"
#include "rtc_base/checks.h"
diff --git a/logging/rtc_event_log/rtc_event_log2text.cc b/logging/rtc_event_log/rtc_event_log2text.cc
index 6ceeaaf..c71a2b8 100644
--- a/logging/rtc_event_log/rtc_event_log2text.cc
+++ b/logging/rtc_event_log/rtc_event_log2text.cc
@@ -13,12 +13,13 @@
#include <iomanip> // setfill, setw
#include <iostream>
#include <map>
+#include <sstream>
#include <string>
#include <utility> // pair
#include "call/video_config.h"
#include "common_types.h" // NOLINT(build/include)
-#include "logging/rtc_event_log/rtc_event_log_parser2.h"
+#include "logging/rtc_event_log/rtc_event_log_parser.h"
#include "modules/audio_coding/audio_network_adaptor/include/audio_network_adaptor_config.h"
#include "modules/rtp_rtcp/source/rtcp_packet/bye.h"
#include "modules/rtp_rtcp/source/rtcp_packet/common_header.h"
@@ -39,7 +40,6 @@
#include "rtc_base/checks.h"
#include "rtc_base/flags.h"
#include "rtc_base/logging.h"
-#include "rtc_base/strings/string_builder.h"
namespace {
@@ -443,7 +443,7 @@
size_t total_length;
uint8_t header[IP_PACKET_SIZE];
webrtc::PacketDirection direction;
- const webrtc::RtpHeaderExtensionMap* extension_map =
+ webrtc::RtpHeaderExtensionMap* extension_map =
parsed_stream.GetRtpHeader(i, &direction, header, &header_length,
&total_length, nullptr);
@@ -583,9 +583,10 @@
case webrtc::ParsedRtcEventLog::AUDIO_PLAYOUT_EVENT: {
if (FLAG_playout) {
- auto audio_playout = parsed_stream.GetAudioPlayout(i);
- std::cout << audio_playout.log_time_us() << "\tAUDIO_PLAYOUT"
- << "\tssrc=" << audio_playout.ssrc << std::endl;
+ uint32_t ssrc;
+ parsed_stream.GetAudioPlayout(i, &ssrc);
+ std::cout << parsed_stream.GetTimestamp(i) << "\tAUDIO_PLAYOUT"
+ << "\tssrc=" << ssrc << std::endl;
}
event_recognized = true;
break;
@@ -593,13 +594,15 @@
case webrtc::ParsedRtcEventLog::LOSS_BASED_BWE_UPDATE: {
if (FLAG_bwe) {
- auto bwe_update = parsed_stream.GetLossBasedBweUpdate(i);
- std::cout << bwe_update.log_time_us() << "\tBWE(LOSS_BASED)"
- << "\tbitrate_bps=" << bwe_update.bitrate_bps
- << "\tfraction_lost="
- << static_cast<unsigned>(bwe_update.fraction_lost)
- << "\texpected_packets=" << bwe_update.expected_packets
- << std::endl;
+ int32_t bitrate_bps;
+ uint8_t fraction_loss;
+ int32_t total_packets;
+ parsed_stream.GetLossBasedBweUpdate(i, &bitrate_bps, &fraction_loss,
+ &total_packets);
+ std::cout << parsed_stream.GetTimestamp(i) << "\tBWE(LOSS_BASED)"
+ << "\tbitrate_bps=" << bitrate_bps << "\tfraction_loss="
+ << static_cast<unsigned>(fraction_loss)
+ << "\ttotal_packets=" << total_packets << std::endl;
}
event_recognized = true;
break;
@@ -608,7 +611,7 @@
case webrtc::ParsedRtcEventLog::DELAY_BASED_BWE_UPDATE: {
if (FLAG_bwe) {
auto bwe_update = parsed_stream.GetDelayBasedBweUpdate(i);
- std::cout << bwe_update.log_time_us() << "\tBWE(DELAY_BASED)"
+ std::cout << parsed_stream.GetTimestamp(i) << "\tBWE(DELAY_BASED)"
<< "\tbitrate_bps=" << bwe_update.bitrate_bps
<< "\tdetector_state="
<< static_cast<int>(bwe_update.detector_state) << std::endl;
@@ -720,31 +723,30 @@
case webrtc::ParsedRtcEventLog::AUDIO_NETWORK_ADAPTATION_EVENT: {
if (FLAG_ana) {
- auto ana_event = parsed_stream.GetAudioNetworkAdaptation(i);
- char buffer[300];
- rtc::SimpleStringBuilder builder(buffer);
- builder << parsed_stream.GetTimestamp(i) << "\tANA_UPDATE";
- if (ana_event.config.bitrate_bps) {
- builder << "\tbitrate_bps=" << *ana_event.config.bitrate_bps;
+ webrtc::AudioEncoderRuntimeConfig ana_config;
+ parsed_stream.GetAudioNetworkAdaptation(i, &ana_config);
+ std::stringstream ss;
+ ss << parsed_stream.GetTimestamp(i) << "\tANA_UPDATE";
+ if (ana_config.bitrate_bps) {
+ ss << "\tbitrate_bps=" << *ana_config.bitrate_bps;
}
- if (ana_event.config.frame_length_ms) {
- builder << "\tframe_length_ms="
- << *ana_event.config.frame_length_ms;
+ if (ana_config.frame_length_ms) {
+ ss << "\tframe_length_ms=" << *ana_config.frame_length_ms;
}
- if (ana_event.config.uplink_packet_loss_fraction) {
- builder << "\tuplink_packet_loss_fraction="
- << *ana_event.config.uplink_packet_loss_fraction;
+ if (ana_config.uplink_packet_loss_fraction) {
+ ss << "\tuplink_packet_loss_fraction="
+ << *ana_config.uplink_packet_loss_fraction;
}
- if (ana_event.config.enable_fec) {
- builder << "\tenable_fec=" << *ana_event.config.enable_fec;
+ if (ana_config.enable_fec) {
+ ss << "\tenable_fec=" << *ana_config.enable_fec;
}
- if (ana_event.config.enable_dtx) {
- builder << "\tenable_dtx=" << *ana_event.config.enable_dtx;
+ if (ana_config.enable_dtx) {
+ ss << "\tenable_dtx=" << *ana_config.enable_dtx;
}
- if (ana_event.config.num_channels) {
- builder << "\tnum_channels=" << *ana_event.config.num_channels;
+ if (ana_config.num_channels) {
+ ss << "\tnum_channels=" << *ana_config.num_channels;
}
- std::cout << builder.str() << std::endl;
+ std::cout << ss.str() << std::endl;
}
event_recognized = true;
break;
@@ -752,7 +754,8 @@
case webrtc::ParsedRtcEventLog::BWE_PROBE_CLUSTER_CREATED_EVENT: {
if (FLAG_probe) {
- auto probe_event = parsed_stream.GetBweProbeClusterCreated(i);
+ webrtc::ParsedRtcEventLog::BweProbeClusterCreatedEvent probe_event =
+ parsed_stream.GetBweProbeClusterCreated(i);
std::cout << parsed_stream.GetTimestamp(i) << "\tPROBE_CREATED("
<< probe_event.id << ")"
<< "\tbitrate_bps=" << probe_event.bitrate_bps
@@ -765,7 +768,7 @@
case webrtc::ParsedRtcEventLog::BWE_PROBE_RESULT_EVENT: {
if (FLAG_probe) {
- webrtc::LoggedBweProbeResultEvent probe_result =
+ webrtc::ParsedRtcEventLog::BweProbeResultEvent probe_result =
parsed_stream.GetBweProbeResult(i);
if (probe_result.failure_reason) {
std::cout << parsed_stream.GetTimestamp(i) << "\tPROBE_SUCCESS("
@@ -786,7 +789,8 @@
case webrtc::ParsedRtcEventLog::ALR_STATE_EVENT: {
if (FLAG_bwe) {
- webrtc::LoggedAlrStateEvent alr_state = parsed_stream.GetAlrState(i);
+ webrtc::ParsedRtcEventLog::AlrStateEvent alr_state =
+ parsed_stream.GetAlrState(i);
std::cout << parsed_stream.GetTimestamp(i) << "\tALR_STATE"
<< "\tin_alr=" << alr_state.in_alr << std::endl;
}
@@ -796,7 +800,7 @@
case webrtc::ParsedRtcEventLog::ICE_CANDIDATE_PAIR_CONFIG: {
if (FLAG_ice) {
- webrtc::LoggedIceCandidatePairConfig ice_cp_config =
+ 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)
@@ -810,7 +814,7 @@
case webrtc::ParsedRtcEventLog::ICE_CANDIDATE_PAIR_EVENT: {
if (FLAG_ice) {
- webrtc::LoggedIceCandidatePairEvent ice_cp_event =
+ 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)
diff --git a/logging/rtc_event_log/rtc_event_log_parser2.cc b/logging/rtc_event_log/rtc_event_log_parser2.cc
deleted file mode 100644
index 9bcad0d..0000000
--- a/logging/rtc_event_log/rtc_event_log_parser2.cc
+++ /dev/null
@@ -1,1248 +0,0 @@
-/*
- * Copyright (c) 2016 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/rtc_event_log_parser2.h"
-
-#include <stdint.h>
-#include <string.h>
-
-#include <algorithm>
-#include <fstream>
-#include <istream> // no-presubmit-check TODO(webrtc:8982)
-#include <limits>
-#include <map>
-#include <utility>
-
-#include "api/rtp_headers.h"
-#include "api/rtpparameters.h"
-#include "logging/rtc_event_log/rtc_event_log.h"
-#include "modules/audio_coding/audio_network_adaptor/include/audio_network_adaptor.h"
-#include "modules/remote_bitrate_estimator/include/bwe_defines.h"
-#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
-#include "modules/rtp_rtcp/source/byte_io.h"
-#include "modules/rtp_rtcp/source/rtp_header_extensions.h"
-#include "modules/rtp_rtcp/source/rtp_utility.h"
-#include "rtc_base/checks.h"
-#include "rtc_base/logging.h"
-#include "rtc_base/protobuf_utils.h"
-#include "rtc_base/ptr_util.h"
-
-namespace webrtc {
-
-namespace {
-RtcpMode GetRuntimeRtcpMode(rtclog::VideoReceiveConfig::RtcpMode rtcp_mode) {
- switch (rtcp_mode) {
- case rtclog::VideoReceiveConfig::RTCP_COMPOUND:
- return RtcpMode::kCompound;
- case rtclog::VideoReceiveConfig::RTCP_REDUCEDSIZE:
- return RtcpMode::kReducedSize;
- }
- RTC_NOTREACHED();
- return RtcpMode::kOff;
-}
-
-ParsedRtcEventLog::EventType GetRuntimeEventType(
- rtclog::Event::EventType event_type) {
- switch (event_type) {
- case rtclog::Event::UNKNOWN_EVENT:
- return ParsedRtcEventLog::EventType::UNKNOWN_EVENT;
- case rtclog::Event::LOG_START:
- return ParsedRtcEventLog::EventType::LOG_START;
- case rtclog::Event::LOG_END:
- return ParsedRtcEventLog::EventType::LOG_END;
- case rtclog::Event::RTP_EVENT:
- return ParsedRtcEventLog::EventType::RTP_EVENT;
- case rtclog::Event::RTCP_EVENT:
- return ParsedRtcEventLog::EventType::RTCP_EVENT;
- case rtclog::Event::AUDIO_PLAYOUT_EVENT:
- return ParsedRtcEventLog::EventType::AUDIO_PLAYOUT_EVENT;
- case rtclog::Event::LOSS_BASED_BWE_UPDATE:
- return ParsedRtcEventLog::EventType::LOSS_BASED_BWE_UPDATE;
- case rtclog::Event::DELAY_BASED_BWE_UPDATE:
- return ParsedRtcEventLog::EventType::DELAY_BASED_BWE_UPDATE;
- case rtclog::Event::VIDEO_RECEIVER_CONFIG_EVENT:
- return ParsedRtcEventLog::EventType::VIDEO_RECEIVER_CONFIG_EVENT;
- case rtclog::Event::VIDEO_SENDER_CONFIG_EVENT:
- return ParsedRtcEventLog::EventType::VIDEO_SENDER_CONFIG_EVENT;
- case rtclog::Event::AUDIO_RECEIVER_CONFIG_EVENT:
- return ParsedRtcEventLog::EventType::AUDIO_RECEIVER_CONFIG_EVENT;
- case rtclog::Event::AUDIO_SENDER_CONFIG_EVENT:
- return ParsedRtcEventLog::EventType::AUDIO_SENDER_CONFIG_EVENT;
- case rtclog::Event::AUDIO_NETWORK_ADAPTATION_EVENT:
- return ParsedRtcEventLog::EventType::AUDIO_NETWORK_ADAPTATION_EVENT;
- case rtclog::Event::BWE_PROBE_CLUSTER_CREATED_EVENT:
- return ParsedRtcEventLog::EventType::BWE_PROBE_CLUSTER_CREATED_EVENT;
- case rtclog::Event::BWE_PROBE_RESULT_EVENT:
- 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;
-}
-
-BandwidthUsage GetRuntimeDetectorState(
- rtclog::DelayBasedBweUpdate::DetectorState detector_state) {
- switch (detector_state) {
- case rtclog::DelayBasedBweUpdate::BWE_NORMAL:
- return BandwidthUsage::kBwNormal;
- case rtclog::DelayBasedBweUpdate::BWE_UNDERUSING:
- return BandwidthUsage::kBwUnderusing;
- case rtclog::DelayBasedBweUpdate::BWE_OVERUSING:
- return BandwidthUsage::kBwOverusing;
- }
- RTC_NOTREACHED();
- 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;
-}
-
-// Return default values for header extensions, to use on streams without stored
-// mapping data. Currently this only applies to audio streams, since the mapping
-// is not stored in the event log.
-// TODO(ivoc): Remove this once this mapping is stored in the event log for
-// audio streams. Tracking bug: webrtc:6399
-webrtc::RtpHeaderExtensionMap GetDefaultHeaderExtensionMap() {
- webrtc::RtpHeaderExtensionMap default_map;
- default_map.Register<AudioLevel>(webrtc::RtpExtension::kAudioLevelDefaultId);
- default_map.Register<TransmissionOffset>(
- webrtc::RtpExtension::kTimestampOffsetDefaultId);
- default_map.Register<AbsoluteSendTime>(
- webrtc::RtpExtension::kAbsSendTimeDefaultId);
- default_map.Register<VideoOrientation>(
- webrtc::RtpExtension::kVideoRotationDefaultId);
- default_map.Register<VideoContentTypeExtension>(
- webrtc::RtpExtension::kVideoContentTypeDefaultId);
- default_map.Register<VideoTimingExtension>(
- webrtc::RtpExtension::kVideoTimingDefaultId);
- default_map.Register<TransportSequenceNumber>(
- webrtc::RtpExtension::kTransportSequenceNumberDefaultId);
- default_map.Register<PlayoutDelayLimits>(
- webrtc::RtpExtension::kPlayoutDelayDefaultId);
- return default_map;
-}
-
-std::pair<uint64_t, bool> ParseVarInt(
- std::istream& stream) { // no-presubmit-check TODO(webrtc:8982)
- uint64_t varint = 0;
- for (size_t bytes_read = 0; bytes_read < 10; ++bytes_read) {
- // The most significant bit of each byte is 0 if it is the last byte in
- // the varint and 1 otherwise. Thus, we take the 7 least significant bits
- // of each byte and shift them 7 bits for each byte read previously to get
- // the (unsigned) integer.
- int byte = stream.get();
- if (stream.eof()) {
- return std::make_pair(varint, false);
- }
- RTC_DCHECK_GE(byte, 0);
- RTC_DCHECK_LE(byte, 255);
- varint |= static_cast<uint64_t>(byte & 0x7F) << (7 * bytes_read);
- if ((byte & 0x80) == 0) {
- return std::make_pair(varint, true);
- }
- }
- return std::make_pair(varint, false);
-}
-
-void GetHeaderExtensions(std::vector<RtpExtension>* header_extensions,
- const RepeatedPtrField<rtclog::RtpHeaderExtension>&
- proto_header_extensions) {
- header_extensions->clear();
- for (auto& p : proto_header_extensions) {
- RTC_CHECK(p.has_name());
- RTC_CHECK(p.has_id());
- const std::string& name = p.name();
- int id = p.id();
- header_extensions->push_back(RtpExtension(name, id));
- }
-}
-
-} // namespace
-
-ParsedRtcEventLog::ParsedRtcEventLog(
- UnconfiguredHeaderExtensions parse_unconfigured_header_extensions)
- : parse_unconfigured_header_extensions_(
- parse_unconfigured_header_extensions) {
- Clear();
-}
-
-void ParsedRtcEventLog::Clear() {
- events_.clear();
- default_extension_map_ = GetDefaultHeaderExtensionMap();
-
- incoming_rtx_ssrcs_.clear();
- incoming_video_ssrcs_.clear();
- incoming_audio_ssrcs_.clear();
- outgoing_rtx_ssrcs_.clear();
- outgoing_video_ssrcs_.clear();
- outgoing_audio_ssrcs_.clear();
-
- incoming_rtp_packets_map_.clear();
- outgoing_rtp_packets_map_.clear();
- incoming_rtp_packets_by_ssrc_.clear();
- outgoing_rtp_packets_by_ssrc_.clear();
- incoming_rtp_packet_views_by_ssrc_.clear();
- outgoing_rtp_packet_views_by_ssrc_.clear();
-
- incoming_rtcp_packets_.clear();
- outgoing_rtcp_packets_.clear();
-
- incoming_rr_.clear();
- outgoing_rr_.clear();
- incoming_sr_.clear();
- outgoing_sr_.clear();
- incoming_nack_.clear();
- outgoing_nack_.clear();
- incoming_remb_.clear();
- outgoing_remb_.clear();
- incoming_transport_feedback_.clear();
- outgoing_transport_feedback_.clear();
-
- start_log_events_.clear();
- stop_log_events_.clear();
- audio_playout_events_.clear();
- audio_network_adaptation_events_.clear();
- bwe_probe_cluster_created_events_.clear();
- bwe_probe_result_events_.clear();
- bwe_delay_updates_.clear();
- bwe_loss_updates_.clear();
- alr_state_events_.clear();
- ice_candidate_pair_configs_.clear();
- ice_candidate_pair_events_.clear();
- audio_recv_configs_.clear();
- audio_send_configs_.clear();
- video_recv_configs_.clear();
- video_send_configs_.clear();
-
- memset(last_incoming_rtcp_packet_, 0, IP_PACKET_SIZE);
- last_incoming_rtcp_packet_length_ = 0;
-
- first_timestamp_ = std::numeric_limits<int64_t>::max();
- last_timestamp_ = std::numeric_limits<int64_t>::min();
-
- incoming_rtp_extensions_maps_.clear();
- outgoing_rtp_extensions_maps_.clear();
-}
-
-bool ParsedRtcEventLog::ParseFile(const std::string& filename) {
- std::ifstream file( // no-presubmit-check TODO(webrtc:8982)
- filename, std::ios_base::in | std::ios_base::binary);
- if (!file.good() || !file.is_open()) {
- RTC_LOG(LS_WARNING) << "Could not open file for reading.";
- return false;
- }
-
- return ParseStream(file);
-}
-
-bool ParsedRtcEventLog::ParseString(const std::string& s) {
- std::istringstream stream( // no-presubmit-check TODO(webrtc:8982)
- s, std::ios_base::in | std::ios_base::binary);
- return ParseStream(stream);
-}
-
-bool ParsedRtcEventLog::ParseStream(
- std::istream& stream) { // no-presubmit-check TODO(webrtc:8982)
- Clear();
- const size_t kMaxEventSize = (1u << 16) - 1;
- std::vector<char> tmp_buffer(kMaxEventSize);
- uint64_t tag;
- uint64_t message_length;
- bool success;
-
- RTC_DCHECK(stream.good());
-
- while (1) {
- // Check whether we have reached end of file.
- stream.peek();
- if (stream.eof()) {
- break;
- }
-
- // Read the next message tag. The tag number is defined as
- // (fieldnumber << 3) | wire_type. In our case, the field number is
- // supposed to be 1 and the wire type for an
- // length-delimited field is 2.
- const uint64_t kExpectedTag = (1 << 3) | 2;
- std::tie(tag, success) = ParseVarInt(stream);
- if (!success) {
- RTC_LOG(LS_WARNING)
- << "Missing field tag from beginning of protobuf event.";
- return false;
- } else if (tag != kExpectedTag) {
- RTC_LOG(LS_WARNING)
- << "Unexpected field tag at beginning of protobuf event.";
- return false;
- }
-
- // Read the length field.
- std::tie(message_length, success) = ParseVarInt(stream);
- if (!success) {
- RTC_LOG(LS_WARNING) << "Missing message length after protobuf field tag.";
- return false;
- } else if (message_length > kMaxEventSize) {
- RTC_LOG(LS_WARNING) << "Protobuf message length is too large.";
- return false;
- }
-
- // Read the next protobuf event to a temporary char buffer.
- stream.read(tmp_buffer.data(), message_length);
- if (stream.gcount() != static_cast<int>(message_length)) {
- RTC_LOG(LS_WARNING) << "Failed to read protobuf message from file.";
- return false;
- }
-
- // Parse the protobuf event from the buffer.
- rtclog::Event event;
- if (!event.ParseFromArray(tmp_buffer.data(), message_length)) {
- RTC_LOG(LS_WARNING) << "Failed to parse protobuf message.";
- return false;
- }
-
- StoreParsedEvent(event);
-
- events_.push_back(event);
- }
-
- // Move packets_streams from map to vector.
- incoming_rtp_packets_by_ssrc_.reserve(incoming_rtp_packets_map_.size());
- for (const auto& kv : incoming_rtp_packets_map_) {
- incoming_rtp_packets_by_ssrc_.emplace_back(LoggedRtpStreamIncoming());
- incoming_rtp_packets_by_ssrc_.back().ssrc = kv.first;
- incoming_rtp_packets_by_ssrc_.back().incoming_packets =
- std::move(kv.second);
- }
- outgoing_rtp_packets_by_ssrc_.reserve(outgoing_rtp_packets_map_.size());
- for (const auto& kv : outgoing_rtp_packets_map_) {
- outgoing_rtp_packets_by_ssrc_.emplace_back(LoggedRtpStreamOutgoing());
- outgoing_rtp_packets_by_ssrc_.back().ssrc = kv.first;
- outgoing_rtp_packets_by_ssrc_.back().outgoing_packets =
- std::move(kv.second);
- }
-
- // Build PacketViews for easier iteration over RTP packets
- for (const auto& stream : incoming_rtp_packets_by_ssrc_) {
- incoming_rtp_packet_views_by_ssrc_.emplace_back(
- LoggedRtpStreamView(stream.ssrc, stream.incoming_packets.data(),
- stream.incoming_packets.size()));
- }
- for (const auto& stream : outgoing_rtp_packets_by_ssrc_) {
- outgoing_rtp_packet_views_by_ssrc_.emplace_back(
- LoggedRtpStreamView(stream.ssrc, stream.outgoing_packets.data(),
- stream.outgoing_packets.size()));
- }
-
- return true;
-}
-
-void ParsedRtcEventLog::StoreParsedEvent(const rtclog::Event& event) {
- if (event.type() != rtclog::Event::VIDEO_RECEIVER_CONFIG_EVENT &&
- event.type() != rtclog::Event::VIDEO_SENDER_CONFIG_EVENT &&
- event.type() != rtclog::Event::AUDIO_RECEIVER_CONFIG_EVENT &&
- event.type() != rtclog::Event::AUDIO_SENDER_CONFIG_EVENT &&
- event.type() != rtclog::Event::LOG_START &&
- event.type() != rtclog::Event::LOG_END) {
- RTC_CHECK(event.has_timestamp_us());
- int64_t timestamp = event.timestamp_us();
- first_timestamp_ = std::min(first_timestamp_, timestamp);
- last_timestamp_ = std::max(last_timestamp_, timestamp);
- }
-
- switch (event.type()) {
- case rtclog::Event::VIDEO_RECEIVER_CONFIG_EVENT: {
- rtclog::StreamConfig config = GetVideoReceiveConfig(event);
- video_recv_configs_.emplace_back(GetTimestamp(event), config);
- incoming_rtp_extensions_maps_[config.remote_ssrc] =
- RtpHeaderExtensionMap(config.rtp_extensions);
- // TODO(terelius): I don't understand the reason for configuring header
- // extensions for the local SSRC. I think it should be removed, but for
- // now I want to preserve the previous functionality.
- incoming_rtp_extensions_maps_[config.local_ssrc] =
- RtpHeaderExtensionMap(config.rtp_extensions);
- incoming_video_ssrcs_.insert(config.remote_ssrc);
- incoming_video_ssrcs_.insert(config.rtx_ssrc);
- incoming_rtx_ssrcs_.insert(config.rtx_ssrc);
- break;
- }
- case rtclog::Event::VIDEO_SENDER_CONFIG_EVENT: {
- std::vector<rtclog::StreamConfig> configs = GetVideoSendConfig(event);
- video_send_configs_.emplace_back(GetTimestamp(event), configs);
- for (const auto& config : configs) {
- outgoing_rtp_extensions_maps_[config.local_ssrc] =
- RtpHeaderExtensionMap(config.rtp_extensions);
- outgoing_rtp_extensions_maps_[config.rtx_ssrc] =
- RtpHeaderExtensionMap(config.rtp_extensions);
- outgoing_video_ssrcs_.insert(config.local_ssrc);
- outgoing_video_ssrcs_.insert(config.rtx_ssrc);
- outgoing_rtx_ssrcs_.insert(config.rtx_ssrc);
- }
- break;
- }
- case rtclog::Event::AUDIO_RECEIVER_CONFIG_EVENT: {
- rtclog::StreamConfig config = GetAudioReceiveConfig(event);
- audio_recv_configs_.emplace_back(GetTimestamp(event), config);
- incoming_rtp_extensions_maps_[config.remote_ssrc] =
- RtpHeaderExtensionMap(config.rtp_extensions);
- incoming_rtp_extensions_maps_[config.local_ssrc] =
- RtpHeaderExtensionMap(config.rtp_extensions);
- incoming_audio_ssrcs_.insert(config.remote_ssrc);
- break;
- }
- case rtclog::Event::AUDIO_SENDER_CONFIG_EVENT: {
- rtclog::StreamConfig config = GetAudioSendConfig(event);
- audio_send_configs_.emplace_back(GetTimestamp(event), config);
- outgoing_rtp_extensions_maps_[config.local_ssrc] =
- RtpHeaderExtensionMap(config.rtp_extensions);
- outgoing_audio_ssrcs_.insert(config.local_ssrc);
- break;
- }
- case rtclog::Event::RTP_EVENT: {
- PacketDirection direction;
- uint8_t header[IP_PACKET_SIZE];
- size_t header_length;
- size_t total_length;
- const RtpHeaderExtensionMap* extension_map = GetRtpHeader(
- event, &direction, header, &header_length, &total_length, nullptr);
- RtpUtility::RtpHeaderParser rtp_parser(header, header_length);
- RTPHeader parsed_header;
- if (extension_map != nullptr) {
- rtp_parser.Parse(&parsed_header, extension_map);
- } else {
- // Use the default extension map.
- // TODO(ivoc): Once configuration of audio streams is stored in the
- // event log, this can be removed.
- // Tracking bug: webrtc:6399
- rtp_parser.Parse(&parsed_header, &default_extension_map_);
- }
- RTC_CHECK(event.has_timestamp_us());
- uint64_t timestamp_us = event.timestamp_us();
- if (direction == kIncomingPacket) {
- incoming_rtp_packets_map_[parsed_header.ssrc].push_back(
- LoggedRtpPacketIncoming(timestamp_us, parsed_header, header_length,
- total_length));
- } else {
- outgoing_rtp_packets_map_[parsed_header.ssrc].push_back(
- LoggedRtpPacketOutgoing(timestamp_us, parsed_header, header_length,
- total_length));
- }
- break;
- }
- case rtclog::Event::RTCP_EVENT: {
- PacketDirection direction;
- uint8_t packet[IP_PACKET_SIZE];
- size_t total_length;
- GetRtcpPacket(event, &direction, packet, &total_length);
- uint64_t timestamp_us = GetTimestamp(event);
- RTC_CHECK_LE(total_length, IP_PACKET_SIZE);
- if (direction == kIncomingPacket) {
- // Currently incoming RTCP packets are logged twice, both for audio and
- // video. Only act on one of them. Compare against the previous parsed
- // incoming RTCP packet.
- if (total_length == last_incoming_rtcp_packet_length_ &&
- memcmp(last_incoming_rtcp_packet_, packet, total_length) == 0)
- break;
- incoming_rtcp_packets_.push_back(
- LoggedRtcpPacketIncoming(timestamp_us, packet, total_length));
- last_incoming_rtcp_packet_length_ = total_length;
- memcpy(last_incoming_rtcp_packet_, packet, total_length);
- } else {
- outgoing_rtcp_packets_.push_back(
- LoggedRtcpPacketOutgoing(timestamp_us, packet, total_length));
- }
- rtcp::CommonHeader header;
- const uint8_t* packet_end = packet + total_length;
- for (const uint8_t* block = packet; block < packet_end;
- block = header.NextPacket()) {
- RTC_CHECK(header.Parse(block, packet_end - block));
- if (header.type() == rtcp::TransportFeedback::kPacketType &&
- header.fmt() == rtcp::TransportFeedback::kFeedbackMessageType) {
- if (direction == kIncomingPacket) {
- incoming_transport_feedback_.emplace_back();
- LoggedRtcpPacketTransportFeedback& parsed_block =
- incoming_transport_feedback_.back();
- parsed_block.timestamp_us = GetTimestamp(event);
- if (!parsed_block.transport_feedback.Parse(header))
- incoming_transport_feedback_.pop_back();
- } else {
- outgoing_transport_feedback_.emplace_back();
- LoggedRtcpPacketTransportFeedback& parsed_block =
- outgoing_transport_feedback_.back();
- parsed_block.timestamp_us = GetTimestamp(event);
- if (!parsed_block.transport_feedback.Parse(header))
- outgoing_transport_feedback_.pop_back();
- }
- } else if (header.type() == rtcp::SenderReport::kPacketType) {
- LoggedRtcpPacketSenderReport parsed_block;
- parsed_block.timestamp_us = GetTimestamp(event);
- if (parsed_block.sr.Parse(header)) {
- if (direction == kIncomingPacket)
- incoming_sr_.push_back(std::move(parsed_block));
- else
- outgoing_sr_.push_back(std::move(parsed_block));
- }
- } else if (header.type() == rtcp::ReceiverReport::kPacketType) {
- LoggedRtcpPacketReceiverReport parsed_block;
- parsed_block.timestamp_us = GetTimestamp(event);
- if (parsed_block.rr.Parse(header)) {
- if (direction == kIncomingPacket)
- incoming_rr_.push_back(std::move(parsed_block));
- else
- outgoing_rr_.push_back(std::move(parsed_block));
- }
- } else if (header.type() == rtcp::Remb::kPacketType &&
- header.fmt() == rtcp::Remb::kFeedbackMessageType) {
- LoggedRtcpPacketRemb parsed_block;
- parsed_block.timestamp_us = GetTimestamp(event);
- if (parsed_block.remb.Parse(header)) {
- if (direction == kIncomingPacket)
- incoming_remb_.push_back(std::move(parsed_block));
- else
- outgoing_remb_.push_back(std::move(parsed_block));
- }
- } else if (header.type() == rtcp::Nack::kPacketType &&
- header.fmt() == rtcp::Nack::kFeedbackMessageType) {
- LoggedRtcpPacketNack parsed_block;
- parsed_block.timestamp_us = GetTimestamp(event);
- if (parsed_block.nack.Parse(header)) {
- if (direction == kIncomingPacket)
- incoming_nack_.push_back(std::move(parsed_block));
- else
- outgoing_nack_.push_back(std::move(parsed_block));
- }
- }
- }
- break;
- }
- case ParsedRtcEventLog::LOG_START: {
- start_log_events_.push_back(LoggedStartEvent(GetTimestamp(event)));
- break;
- }
- case ParsedRtcEventLog::LOG_END: {
- stop_log_events_.push_back(LoggedStopEvent(GetTimestamp(event)));
- break;
- }
- case ParsedRtcEventLog::AUDIO_PLAYOUT_EVENT: {
- LoggedAudioPlayoutEvent playout_event = GetAudioPlayout(event);
- audio_playout_events_[playout_event.ssrc].push_back(
- playout_event.timestamp_us);
- break;
- }
- case ParsedRtcEventLog::LOSS_BASED_BWE_UPDATE: {
- bwe_loss_updates_.push_back(GetLossBasedBweUpdate(event));
- break;
- }
- case ParsedRtcEventLog::DELAY_BASED_BWE_UPDATE: {
- bwe_delay_updates_.push_back(GetDelayBasedBweUpdate(event));
- break;
- }
- case ParsedRtcEventLog::AUDIO_NETWORK_ADAPTATION_EVENT: {
- LoggedAudioNetworkAdaptationEvent ana_event =
- GetAudioNetworkAdaptation(event);
- audio_network_adaptation_events_.push_back(ana_event);
- break;
- }
- case ParsedRtcEventLog::BWE_PROBE_CLUSTER_CREATED_EVENT: {
- bwe_probe_cluster_created_events_.push_back(
- GetBweProbeClusterCreated(event));
- break;
- }
- case ParsedRtcEventLog::BWE_PROBE_RESULT_EVENT: {
- bwe_probe_result_events_.push_back(GetBweProbeResult(event));
- break;
- }
- case ParsedRtcEventLog::ALR_STATE_EVENT: {
- alr_state_events_.push_back(GetAlrState(event));
- break;
- }
- case ParsedRtcEventLog::ICE_CANDIDATE_PAIR_CONFIG: {
- ice_candidate_pair_configs_.push_back(GetIceCandidatePairConfig(event));
- break;
- }
- case ParsedRtcEventLog::ICE_CANDIDATE_PAIR_EVENT: {
- ice_candidate_pair_events_.push_back(GetIceCandidatePairEvent(event));
- break;
- }
- case ParsedRtcEventLog::UNKNOWN_EVENT: {
- break;
- }
- }
-}
-
-size_t ParsedRtcEventLog::GetNumberOfEvents() const {
- return events_.size();
-}
-
-int64_t ParsedRtcEventLog::GetTimestamp(size_t index) const {
- RTC_CHECK_LT(index, GetNumberOfEvents());
- const rtclog::Event& event = events_[index];
- return GetTimestamp(event);
-}
-
-int64_t ParsedRtcEventLog::GetTimestamp(const rtclog::Event& event) const {
- RTC_CHECK(event.has_timestamp_us());
- return event.timestamp_us();
-}
-
-ParsedRtcEventLog::EventType ParsedRtcEventLog::GetEventType(
- size_t index) const {
- RTC_CHECK_LT(index, GetNumberOfEvents());
- const rtclog::Event& event = events_[index];
- RTC_CHECK(event.has_type());
- return GetRuntimeEventType(event.type());
-}
-
-// The header must have space for at least IP_PACKET_SIZE bytes.
-const webrtc::RtpHeaderExtensionMap* ParsedRtcEventLog::GetRtpHeader(
- size_t index,
- PacketDirection* incoming,
- uint8_t* header,
- size_t* header_length,
- size_t* total_length,
- int* probe_cluster_id) const {
- RTC_CHECK_LT(index, GetNumberOfEvents());
- const rtclog::Event& event = events_[index];
- return GetRtpHeader(event, incoming, header, header_length, total_length,
- probe_cluster_id);
-}
-
-const webrtc::RtpHeaderExtensionMap* ParsedRtcEventLog::GetRtpHeader(
- const rtclog::Event& event,
- PacketDirection* incoming,
- uint8_t* header,
- size_t* header_length,
- size_t* total_length,
- int* probe_cluster_id) const {
- RTC_CHECK(event.has_type());
- RTC_CHECK_EQ(event.type(), rtclog::Event::RTP_EVENT);
- RTC_CHECK(event.has_rtp_packet());
- const rtclog::RtpPacket& rtp_packet = event.rtp_packet();
- // Get direction of packet.
- RTC_CHECK(rtp_packet.has_incoming());
- if (incoming != nullptr) {
- *incoming = rtp_packet.incoming() ? kIncomingPacket : kOutgoingPacket;
- }
- // Get packet length.
- RTC_CHECK(rtp_packet.has_packet_length());
- if (total_length != nullptr) {
- *total_length = rtp_packet.packet_length();
- }
- // Get header length.
- RTC_CHECK(rtp_packet.has_header());
- if (header_length != nullptr) {
- *header_length = rtp_packet.header().size();
- }
- if (probe_cluster_id != nullptr) {
- if (rtp_packet.has_probe_cluster_id()) {
- *probe_cluster_id = rtp_packet.probe_cluster_id();
- RTC_CHECK_NE(*probe_cluster_id, PacedPacketInfo::kNotAProbe);
- } else {
- *probe_cluster_id = PacedPacketInfo::kNotAProbe;
- }
- }
- // Get header contents.
- if (header != nullptr) {
- const size_t kMinRtpHeaderSize = 12;
- RTC_CHECK_GE(rtp_packet.header().size(), kMinRtpHeaderSize);
- RTC_CHECK_LE(rtp_packet.header().size(),
- static_cast<size_t>(IP_PACKET_SIZE));
- memcpy(header, rtp_packet.header().data(), rtp_packet.header().size());
- uint32_t ssrc = ByteReader<uint32_t>::ReadBigEndian(header + 8);
- auto& extensions_maps = rtp_packet.incoming()
- ? incoming_rtp_extensions_maps_
- : outgoing_rtp_extensions_maps_;
- auto it = extensions_maps.find(ssrc);
- if (it != extensions_maps.end()) {
- return &(it->second);
- }
- if (parse_unconfigured_header_extensions_ ==
- UnconfiguredHeaderExtensions::kAttemptWebrtcDefaultConfig) {
- RTC_LOG(LS_WARNING) << "Using default header extension map for SSRC "
- << ssrc;
- extensions_maps.insert(std::make_pair(ssrc, default_extension_map_));
- return &default_extension_map_;
- }
- }
- return nullptr;
-}
-
-// The packet must have space for at least IP_PACKET_SIZE bytes.
-void ParsedRtcEventLog::GetRtcpPacket(size_t index,
- PacketDirection* incoming,
- uint8_t* packet,
- size_t* length) const {
- RTC_CHECK_LT(index, GetNumberOfEvents());
- const rtclog::Event& event = events_[index];
- GetRtcpPacket(event, incoming, packet, length);
-}
-
-void ParsedRtcEventLog::GetRtcpPacket(const rtclog::Event& event,
- PacketDirection* incoming,
- uint8_t* packet,
- size_t* length) const {
- RTC_CHECK(event.has_type());
- RTC_CHECK_EQ(event.type(), rtclog::Event::RTCP_EVENT);
- RTC_CHECK(event.has_rtcp_packet());
- const rtclog::RtcpPacket& rtcp_packet = event.rtcp_packet();
- // Get direction of packet.
- RTC_CHECK(rtcp_packet.has_incoming());
- if (incoming != nullptr) {
- *incoming = rtcp_packet.incoming() ? kIncomingPacket : kOutgoingPacket;
- }
- // Get packet length.
- RTC_CHECK(rtcp_packet.has_packet_data());
- if (length != nullptr) {
- *length = rtcp_packet.packet_data().size();
- }
- // Get packet contents.
- if (packet != nullptr) {
- RTC_CHECK_LE(rtcp_packet.packet_data().size(),
- static_cast<unsigned>(IP_PACKET_SIZE));
- memcpy(packet, rtcp_packet.packet_data().data(),
- rtcp_packet.packet_data().size());
- }
-}
-
-rtclog::StreamConfig ParsedRtcEventLog::GetVideoReceiveConfig(
- size_t index) const {
- RTC_CHECK_LT(index, GetNumberOfEvents());
- return GetVideoReceiveConfig(events_[index]);
-}
-
-rtclog::StreamConfig ParsedRtcEventLog::GetVideoReceiveConfig(
- const rtclog::Event& event) const {
- rtclog::StreamConfig config;
- RTC_CHECK(event.has_type());
- RTC_CHECK_EQ(event.type(), rtclog::Event::VIDEO_RECEIVER_CONFIG_EVENT);
- RTC_CHECK(event.has_video_receiver_config());
- const rtclog::VideoReceiveConfig& receiver_config =
- event.video_receiver_config();
- // Get SSRCs.
- RTC_CHECK(receiver_config.has_remote_ssrc());
- config.remote_ssrc = receiver_config.remote_ssrc();
- RTC_CHECK(receiver_config.has_local_ssrc());
- config.local_ssrc = receiver_config.local_ssrc();
- config.rtx_ssrc = 0;
- // Get RTCP settings.
- RTC_CHECK(receiver_config.has_rtcp_mode());
- config.rtcp_mode = GetRuntimeRtcpMode(receiver_config.rtcp_mode());
- RTC_CHECK(receiver_config.has_remb());
- config.remb = receiver_config.remb();
-
- // Get RTX map.
- std::map<uint32_t, const rtclog::RtxConfig> rtx_map;
- for (int i = 0; i < receiver_config.rtx_map_size(); i++) {
- const rtclog::RtxMap& map = receiver_config.rtx_map(i);
- RTC_CHECK(map.has_payload_type());
- RTC_CHECK(map.has_config());
- RTC_CHECK(map.config().has_rtx_ssrc());
- RTC_CHECK(map.config().has_rtx_payload_type());
- rtx_map.insert(std::make_pair(map.payload_type(), map.config()));
- }
-
- // Get header extensions.
- GetHeaderExtensions(&config.rtp_extensions,
- receiver_config.header_extensions());
- // Get decoders.
- config.codecs.clear();
- for (int i = 0; i < receiver_config.decoders_size(); i++) {
- RTC_CHECK(receiver_config.decoders(i).has_name());
- RTC_CHECK(receiver_config.decoders(i).has_payload_type());
- int rtx_payload_type = 0;
- auto rtx_it = rtx_map.find(receiver_config.decoders(i).payload_type());
- if (rtx_it != rtx_map.end()) {
- rtx_payload_type = rtx_it->second.rtx_payload_type();
- if (config.rtx_ssrc != 0 &&
- config.rtx_ssrc != rtx_it->second.rtx_ssrc()) {
- RTC_LOG(LS_WARNING)
- << "RtcEventLog protobuf contained different SSRCs for "
- "different received RTX payload types. Will only use "
- "rtx_ssrc = "
- << config.rtx_ssrc << ".";
- } else {
- config.rtx_ssrc = rtx_it->second.rtx_ssrc();
- }
- }
- config.codecs.emplace_back(receiver_config.decoders(i).name(),
- receiver_config.decoders(i).payload_type(),
- rtx_payload_type);
- }
- return config;
-}
-
-std::vector<rtclog::StreamConfig> ParsedRtcEventLog::GetVideoSendConfig(
- size_t index) const {
- RTC_CHECK_LT(index, GetNumberOfEvents());
- return GetVideoSendConfig(events_[index]);
-}
-
-std::vector<rtclog::StreamConfig> ParsedRtcEventLog::GetVideoSendConfig(
- const rtclog::Event& event) const {
- std::vector<rtclog::StreamConfig> configs;
- RTC_CHECK(event.has_type());
- RTC_CHECK_EQ(event.type(), rtclog::Event::VIDEO_SENDER_CONFIG_EVENT);
- RTC_CHECK(event.has_video_sender_config());
- const rtclog::VideoSendConfig& sender_config = event.video_sender_config();
- if (sender_config.rtx_ssrcs_size() > 0 &&
- sender_config.ssrcs_size() != sender_config.rtx_ssrcs_size()) {
- RTC_LOG(WARNING)
- << "VideoSendConfig is configured for RTX but the number of "
- "SSRCs doesn't match the number of RTX SSRCs.";
- }
- configs.resize(sender_config.ssrcs_size());
- for (int i = 0; i < sender_config.ssrcs_size(); i++) {
- // Get SSRCs.
- configs[i].local_ssrc = sender_config.ssrcs(i);
- if (sender_config.rtx_ssrcs_size() > 0 &&
- i < sender_config.rtx_ssrcs_size()) {
- RTC_CHECK(sender_config.has_rtx_payload_type());
- configs[i].rtx_ssrc = sender_config.rtx_ssrcs(i);
- }
- // Get header extensions.
- GetHeaderExtensions(&configs[i].rtp_extensions,
- sender_config.header_extensions());
-
- // Get the codec.
- RTC_CHECK(sender_config.has_encoder());
- RTC_CHECK(sender_config.encoder().has_name());
- RTC_CHECK(sender_config.encoder().has_payload_type());
- configs[i].codecs.emplace_back(
- sender_config.encoder().name(), sender_config.encoder().payload_type(),
- sender_config.has_rtx_payload_type() ? sender_config.rtx_payload_type()
- : 0);
- }
- return configs;
-}
-
-rtclog::StreamConfig ParsedRtcEventLog::GetAudioReceiveConfig(
- size_t index) const {
- RTC_CHECK_LT(index, GetNumberOfEvents());
- return GetAudioReceiveConfig(events_[index]);
-}
-
-rtclog::StreamConfig ParsedRtcEventLog::GetAudioReceiveConfig(
- const rtclog::Event& event) const {
- rtclog::StreamConfig config;
- RTC_CHECK(event.has_type());
- RTC_CHECK_EQ(event.type(), rtclog::Event::AUDIO_RECEIVER_CONFIG_EVENT);
- RTC_CHECK(event.has_audio_receiver_config());
- const rtclog::AudioReceiveConfig& receiver_config =
- event.audio_receiver_config();
- // Get SSRCs.
- RTC_CHECK(receiver_config.has_remote_ssrc());
- config.remote_ssrc = receiver_config.remote_ssrc();
- RTC_CHECK(receiver_config.has_local_ssrc());
- config.local_ssrc = receiver_config.local_ssrc();
- // Get header extensions.
- GetHeaderExtensions(&config.rtp_extensions,
- receiver_config.header_extensions());
- return config;
-}
-
-rtclog::StreamConfig ParsedRtcEventLog::GetAudioSendConfig(size_t index) const {
- RTC_CHECK_LT(index, GetNumberOfEvents());
- return GetAudioSendConfig(events_[index]);
-}
-
-rtclog::StreamConfig ParsedRtcEventLog::GetAudioSendConfig(
- const rtclog::Event& event) const {
- rtclog::StreamConfig config;
- RTC_CHECK(event.has_type());
- RTC_CHECK_EQ(event.type(), rtclog::Event::AUDIO_SENDER_CONFIG_EVENT);
- RTC_CHECK(event.has_audio_sender_config());
- const rtclog::AudioSendConfig& sender_config = event.audio_sender_config();
- // Get SSRCs.
- RTC_CHECK(sender_config.has_ssrc());
- config.local_ssrc = sender_config.ssrc();
- // Get header extensions.
- GetHeaderExtensions(&config.rtp_extensions,
- sender_config.header_extensions());
- return config;
-}
-
-LoggedAudioPlayoutEvent ParsedRtcEventLog::GetAudioPlayout(size_t index) const {
- RTC_CHECK_LT(index, GetNumberOfEvents());
- const rtclog::Event& event = events_[index];
- return GetAudioPlayout(event);
-}
-
-LoggedAudioPlayoutEvent ParsedRtcEventLog::GetAudioPlayout(
- const rtclog::Event& event) const {
- RTC_CHECK(event.has_type());
- RTC_CHECK_EQ(event.type(), rtclog::Event::AUDIO_PLAYOUT_EVENT);
- RTC_CHECK(event.has_audio_playout_event());
- const rtclog::AudioPlayoutEvent& playout_event = event.audio_playout_event();
- LoggedAudioPlayoutEvent res;
- res.timestamp_us = GetTimestamp(event);
- RTC_CHECK(playout_event.has_local_ssrc());
- res.ssrc = playout_event.local_ssrc();
- return res;
-}
-
-LoggedBweLossBasedUpdate ParsedRtcEventLog::GetLossBasedBweUpdate(
- size_t index) const {
- RTC_CHECK_LT(index, GetNumberOfEvents());
- const rtclog::Event& event = events_[index];
- return GetLossBasedBweUpdate(event);
-}
-
-LoggedBweLossBasedUpdate ParsedRtcEventLog::GetLossBasedBweUpdate(
- const rtclog::Event& event) const {
- RTC_CHECK(event.has_type());
- RTC_CHECK_EQ(event.type(), rtclog::Event::LOSS_BASED_BWE_UPDATE);
- RTC_CHECK(event.has_loss_based_bwe_update());
- const rtclog::LossBasedBweUpdate& loss_event = event.loss_based_bwe_update();
-
- LoggedBweLossBasedUpdate bwe_update;
- bwe_update.timestamp_us = GetTimestamp(event);
- RTC_CHECK(loss_event.has_bitrate_bps());
- bwe_update.bitrate_bps = loss_event.bitrate_bps();
- RTC_CHECK(loss_event.has_fraction_loss());
- bwe_update.fraction_lost = loss_event.fraction_loss();
- RTC_CHECK(loss_event.has_total_packets());
- bwe_update.expected_packets = loss_event.total_packets();
- return bwe_update;
-}
-
-LoggedBweDelayBasedUpdate ParsedRtcEventLog::GetDelayBasedBweUpdate(
- size_t index) const {
- RTC_CHECK_LT(index, GetNumberOfEvents());
- const rtclog::Event& event = events_[index];
- return GetDelayBasedBweUpdate(event);
-}
-
-LoggedBweDelayBasedUpdate ParsedRtcEventLog::GetDelayBasedBweUpdate(
- const rtclog::Event& event) const {
- RTC_CHECK(event.has_type());
- RTC_CHECK_EQ(event.type(), rtclog::Event::DELAY_BASED_BWE_UPDATE);
- RTC_CHECK(event.has_delay_based_bwe_update());
- const rtclog::DelayBasedBweUpdate& delay_event =
- event.delay_based_bwe_update();
-
- LoggedBweDelayBasedUpdate res;
- res.timestamp_us = GetTimestamp(event);
- RTC_CHECK(delay_event.has_bitrate_bps());
- res.bitrate_bps = delay_event.bitrate_bps();
- RTC_CHECK(delay_event.has_detector_state());
- res.detector_state = GetRuntimeDetectorState(delay_event.detector_state());
- return res;
-}
-
-LoggedAudioNetworkAdaptationEvent ParsedRtcEventLog::GetAudioNetworkAdaptation(
- size_t index) const {
- RTC_CHECK_LT(index, GetNumberOfEvents());
- const rtclog::Event& event = events_[index];
- return GetAudioNetworkAdaptation(event);
-}
-
-LoggedAudioNetworkAdaptationEvent ParsedRtcEventLog::GetAudioNetworkAdaptation(
- const rtclog::Event& event) const {
- RTC_CHECK(event.has_type());
- RTC_CHECK_EQ(event.type(), rtclog::Event::AUDIO_NETWORK_ADAPTATION_EVENT);
- RTC_CHECK(event.has_audio_network_adaptation());
- const rtclog::AudioNetworkAdaptation& ana_event =
- event.audio_network_adaptation();
-
- LoggedAudioNetworkAdaptationEvent res;
- res.timestamp_us = GetTimestamp(event);
- if (ana_event.has_bitrate_bps())
- res.config.bitrate_bps = ana_event.bitrate_bps();
- if (ana_event.has_enable_fec())
- res.config.enable_fec = ana_event.enable_fec();
- if (ana_event.has_enable_dtx())
- res.config.enable_dtx = ana_event.enable_dtx();
- if (ana_event.has_frame_length_ms())
- res.config.frame_length_ms = ana_event.frame_length_ms();
- if (ana_event.has_num_channels())
- res.config.num_channels = ana_event.num_channels();
- if (ana_event.has_uplink_packet_loss_fraction())
- res.config.uplink_packet_loss_fraction =
- ana_event.uplink_packet_loss_fraction();
- return res;
-}
-
-LoggedBweProbeClusterCreatedEvent ParsedRtcEventLog::GetBweProbeClusterCreated(
- size_t index) const {
- RTC_CHECK_LT(index, GetNumberOfEvents());
- const rtclog::Event& event = events_[index];
- return GetBweProbeClusterCreated(event);
-}
-
-LoggedBweProbeClusterCreatedEvent ParsedRtcEventLog::GetBweProbeClusterCreated(
- const rtclog::Event& event) const {
- RTC_CHECK(event.has_type());
- RTC_CHECK_EQ(event.type(), rtclog::Event::BWE_PROBE_CLUSTER_CREATED_EVENT);
- RTC_CHECK(event.has_probe_cluster());
- const rtclog::BweProbeCluster& pcc_event = event.probe_cluster();
- LoggedBweProbeClusterCreatedEvent res;
- res.timestamp_us = GetTimestamp(event);
- RTC_CHECK(pcc_event.has_id());
- res.id = pcc_event.id();
- RTC_CHECK(pcc_event.has_bitrate_bps());
- res.bitrate_bps = pcc_event.bitrate_bps();
- RTC_CHECK(pcc_event.has_min_packets());
- res.min_packets = pcc_event.min_packets();
- RTC_CHECK(pcc_event.has_min_bytes());
- res.min_bytes = pcc_event.min_bytes();
- return res;
-}
-
-LoggedBweProbeResultEvent ParsedRtcEventLog::GetBweProbeResult(
- size_t index) const {
- RTC_CHECK_LT(index, GetNumberOfEvents());
- const rtclog::Event& event = events_[index];
- return GetBweProbeResult(event);
-}
-
-LoggedBweProbeResultEvent ParsedRtcEventLog::GetBweProbeResult(
- const rtclog::Event& event) const {
- RTC_CHECK(event.has_type());
- RTC_CHECK_EQ(event.type(), rtclog::Event::BWE_PROBE_RESULT_EVENT);
- RTC_CHECK(event.has_probe_result());
- const rtclog::BweProbeResult& pr_event = event.probe_result();
- LoggedBweProbeResultEvent res;
- res.timestamp_us = GetTimestamp(event);
- RTC_CHECK(pr_event.has_id());
- res.id = pr_event.id();
-
- RTC_CHECK(pr_event.has_result());
- if (pr_event.result() == rtclog::BweProbeResult::SUCCESS) {
- RTC_CHECK(pr_event.has_bitrate_bps());
- res.bitrate_bps = pr_event.bitrate_bps();
- } else if (pr_event.result() ==
- rtclog::BweProbeResult::INVALID_SEND_RECEIVE_INTERVAL) {
- res.failure_reason = ProbeFailureReason::kInvalidSendReceiveInterval;
- } else if (pr_event.result() ==
- rtclog::BweProbeResult::INVALID_SEND_RECEIVE_RATIO) {
- res.failure_reason = ProbeFailureReason::kInvalidSendReceiveRatio;
- } else if (pr_event.result() == rtclog::BweProbeResult::TIMEOUT) {
- res.failure_reason = ProbeFailureReason::kTimeout;
- } else {
- RTC_NOTREACHED();
- }
-
- return res;
-}
-
-LoggedAlrStateEvent ParsedRtcEventLog::GetAlrState(size_t index) const {
- RTC_CHECK_LT(index, GetNumberOfEvents());
- const rtclog::Event& event = events_[index];
- return GetAlrState(event);
-}
-
-LoggedAlrStateEvent ParsedRtcEventLog::GetAlrState(
- const rtclog::Event& event) const {
- RTC_CHECK(event.has_type());
- RTC_CHECK_EQ(event.type(), rtclog::Event::ALR_STATE_EVENT);
- RTC_CHECK(event.has_alr_state());
- const rtclog::AlrState& alr_event = event.alr_state();
- LoggedAlrStateEvent res;
- res.timestamp_us = GetTimestamp(event);
- RTC_CHECK(alr_event.has_in_alr());
- res.in_alr = alr_event.in_alr();
-
- return res;
-}
-
-LoggedIceCandidatePairConfig ParsedRtcEventLog::GetIceCandidatePairConfig(
- size_t index) const {
- RTC_CHECK_LT(index, GetNumberOfEvents());
- const rtclog::Event& rtc_event = events_[index];
- return GetIceCandidatePairConfig(rtc_event);
-}
-
-LoggedIceCandidatePairConfig ParsedRtcEventLog::GetIceCandidatePairConfig(
- const rtclog::Event& rtc_event) const {
- RTC_CHECK(rtc_event.has_type());
- RTC_CHECK_EQ(rtc_event.type(), rtclog::Event::ICE_CANDIDATE_PAIR_CONFIG);
- LoggedIceCandidatePairConfig res;
- const rtclog::IceCandidatePairConfig& config =
- rtc_event.ice_candidate_pair_config();
- res.timestamp_us = GetTimestamp(rtc_event);
- 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;
-}
-
-LoggedIceCandidatePairEvent ParsedRtcEventLog::GetIceCandidatePairEvent(
- size_t index) const {
- RTC_CHECK_LT(index, GetNumberOfEvents());
- const rtclog::Event& rtc_event = events_[index];
- return GetIceCandidatePairEvent(rtc_event);
-}
-
-LoggedIceCandidatePairEvent ParsedRtcEventLog::GetIceCandidatePairEvent(
- const rtclog::Event& rtc_event) const {
- RTC_CHECK(rtc_event.has_type());
- RTC_CHECK_EQ(rtc_event.type(), rtclog::Event::ICE_CANDIDATE_PAIR_EVENT);
- LoggedIceCandidatePairEvent res;
- const rtclog::IceCandidatePairEvent& event =
- rtc_event.ice_candidate_pair_event();
- res.timestamp_us = GetTimestamp(rtc_event);
- 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(
- uint32_t ssrc,
- PacketDirection direction) const {
- if (direction == kIncomingPacket) {
- if (std::find(incoming_video_ssrcs_.begin(), incoming_video_ssrcs_.end(),
- ssrc) != incoming_video_ssrcs_.end()) {
- return MediaType::VIDEO;
- }
- if (std::find(incoming_audio_ssrcs_.begin(), incoming_audio_ssrcs_.end(),
- ssrc) != incoming_audio_ssrcs_.end()) {
- return MediaType::AUDIO;
- }
- } else {
- if (std::find(outgoing_video_ssrcs_.begin(), outgoing_video_ssrcs_.end(),
- ssrc) != outgoing_video_ssrcs_.end()) {
- return MediaType::VIDEO;
- }
- if (std::find(outgoing_audio_ssrcs_.begin(), outgoing_audio_ssrcs_.end(),
- ssrc) != outgoing_audio_ssrcs_.end()) {
- return MediaType::AUDIO;
- }
- }
- return MediaType::ANY;
-}
-
-} // namespace webrtc
diff --git a/logging/rtc_event_log/rtc_event_log_parser2.h b/logging/rtc_event_log/rtc_event_log_parser2.h
deleted file mode 100644
index dfc607d..0000000
--- a/logging/rtc_event_log/rtc_event_log_parser2.h
+++ /dev/null
@@ -1,920 +0,0 @@
-/*
- * Copyright (c) 2016 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_RTC_EVENT_LOG_PARSER2_H_
-#define LOGGING_RTC_EVENT_LOG_RTC_EVENT_LOG_PARSER2_H_
-
-#include <iterator>
-#include <map>
-#include <set>
-#include <string>
-#include <utility> // pair
-#include <vector>
-
-#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"
-#include "modules/audio_coding/audio_network_adaptor/include/audio_network_adaptor.h"
-#include "modules/rtp_rtcp/include/rtp_header_extension_map.h"
-#include "modules/rtp_rtcp/source/rtcp_packet/common_header.h"
-#include "modules/rtp_rtcp/source/rtcp_packet/nack.h"
-#include "modules/rtp_rtcp/source/rtcp_packet/receiver_report.h"
-#include "modules/rtp_rtcp/source/rtcp_packet/remb.h"
-#include "modules/rtp_rtcp/source/rtcp_packet/sender_report.h"
-#include "modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h"
-#include "rtc_base/ignore_wundef.h"
-
-// Files generated at build-time by the protobuf compiler.
-RTC_PUSH_IGNORING_WUNDEF()
-#ifdef WEBRTC_ANDROID_PLATFORM_BUILD
-#include "external/webrtc/webrtc/logging/rtc_event_log/rtc_event_log.pb.h"
-#else
-#include "logging/rtc_event_log/rtc_event_log.pb.h"
-#endif
-RTC_POP_IGNORING_WUNDEF()
-
-namespace webrtc {
-
-enum class BandwidthUsage;
-struct AudioEncoderRuntimeConfig;
-
-struct LoggedAlrStateEvent {
- int64_t timestamp_us;
- bool in_alr;
- int64_t log_time_us() const { return timestamp_us; }
- int64_t log_time_ms() const { return timestamp_us / 1000; }
-};
-
-struct LoggedAudioPlayoutEvent {
- int64_t timestamp_us;
- uint32_t ssrc;
- int64_t log_time_us() const { return timestamp_us; }
- int64_t log_time_ms() const { return timestamp_us / 1000; }
-};
-
-struct LoggedAudioNetworkAdaptationEvent {
- int64_t timestamp_us;
- AudioEncoderRuntimeConfig config;
- int64_t log_time_us() const { return timestamp_us; }
- int64_t log_time_ms() const { return timestamp_us / 1000; }
-};
-
-struct LoggedBweDelayBasedUpdate {
- int64_t timestamp_us;
- int32_t bitrate_bps;
- BandwidthUsage detector_state;
- int64_t log_time_us() const { return timestamp_us; }
- int64_t log_time_ms() const { return timestamp_us / 1000; }
-};
-
-struct LoggedBweLossBasedUpdate {
- int64_t timestamp_us;
- int32_t bitrate_bps;
- uint8_t fraction_lost;
- int32_t expected_packets;
- int64_t log_time_us() const { return timestamp_us; }
- int64_t log_time_ms() const { return timestamp_us / 1000; }
-};
-
-struct LoggedBweProbeClusterCreatedEvent {
- int64_t timestamp_us;
- uint32_t id;
- uint64_t bitrate_bps;
- uint32_t min_packets;
- uint32_t min_bytes;
- int64_t log_time_us() const { return timestamp_us; }
- int64_t log_time_ms() const { return timestamp_us / 1000; }
-};
-
-struct LoggedBweProbeResultEvent {
- int64_t timestamp_us;
- uint32_t id;
- rtc::Optional<uint64_t> bitrate_bps;
- rtc::Optional<ProbeFailureReason> failure_reason;
- int64_t log_time_us() const { return timestamp_us; }
- int64_t log_time_ms() const { return timestamp_us / 1000; }
-};
-
-struct LoggedIceCandidatePairConfig {
- int64_t timestamp_us;
- 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;
- int64_t log_time_us() const { return timestamp_us; }
- int64_t log_time_ms() const { return timestamp_us / 1000; }
-};
-
-struct LoggedIceCandidatePairEvent {
- int64_t timestamp_us;
- IceCandidatePairEventType type;
- uint32_t candidate_pair_id;
- int64_t log_time_us() const { return timestamp_us; }
- int64_t log_time_ms() const { return timestamp_us / 1000; }
-};
-
-struct LoggedRtpPacket {
- LoggedRtpPacket(uint64_t timestamp_us,
- RTPHeader header,
- size_t header_length,
- size_t total_length)
- : timestamp_us(timestamp_us),
- header(header),
- header_length(header_length),
- total_length(total_length) {}
- int64_t timestamp_us;
- // TODO(terelius): This allocates space for 15 CSRCs even if none are used.
- RTPHeader header;
- size_t header_length;
- size_t total_length;
- int64_t log_time_us() const { return timestamp_us; }
- int64_t log_time_ms() const { return timestamp_us / 1000; }
-};
-
-struct LoggedRtpPacketIncoming {
- LoggedRtpPacketIncoming(uint64_t timestamp_us,
- RTPHeader header,
- size_t header_length,
- size_t total_length)
- : rtp(timestamp_us, header, header_length, total_length) {}
- LoggedRtpPacket rtp;
- int64_t log_time_us() const { return rtp.timestamp_us; }
- int64_t log_time_ms() const { return rtp.timestamp_us / 1000; }
-};
-
-struct LoggedRtpPacketOutgoing {
- LoggedRtpPacketOutgoing(uint64_t timestamp_us,
- RTPHeader header,
- size_t header_length,
- size_t total_length)
- : rtp(timestamp_us, header, header_length, total_length) {}
- LoggedRtpPacket rtp;
- int64_t log_time_us() const { return rtp.timestamp_us; }
- int64_t log_time_ms() const { return rtp.timestamp_us / 1000; }
-};
-
-struct LoggedRtcpPacket {
- LoggedRtcpPacket(uint64_t timestamp_us,
- const uint8_t* packet,
- size_t total_length)
- : timestamp_us(timestamp_us), raw_data(packet, packet + total_length) {}
- int64_t timestamp_us;
- std::vector<uint8_t> raw_data;
- int64_t log_time_us() const { return timestamp_us; }
- int64_t log_time_ms() const { return timestamp_us / 1000; }
-};
-
-struct LoggedRtcpPacketIncoming {
- LoggedRtcpPacketIncoming(uint64_t timestamp_us,
- const uint8_t* packet,
- size_t total_length)
- : rtcp(timestamp_us, packet, total_length) {}
- LoggedRtcpPacket rtcp;
- int64_t log_time_us() const { return rtcp.timestamp_us; }
- int64_t log_time_ms() const { return rtcp.timestamp_us / 1000; }
-};
-
-struct LoggedRtcpPacketOutgoing {
- LoggedRtcpPacketOutgoing(uint64_t timestamp_us,
- const uint8_t* packet,
- size_t total_length)
- : rtcp(timestamp_us, packet, total_length) {}
- LoggedRtcpPacket rtcp;
- int64_t log_time_us() const { return rtcp.timestamp_us; }
- int64_t log_time_ms() const { return rtcp.timestamp_us / 1000; }
-};
-
-struct LoggedRtcpPacketReceiverReport {
- int64_t timestamp_us;
- rtcp::ReceiverReport rr;
- int64_t log_time_us() const { return timestamp_us; }
- int64_t log_time_ms() const { return timestamp_us / 1000; }
-};
-
-struct LoggedRtcpPacketSenderReport {
- int64_t timestamp_us;
- rtcp::SenderReport sr;
- int64_t log_time_us() const { return timestamp_us; }
- int64_t log_time_ms() const { return timestamp_us / 1000; }
-};
-
-struct LoggedRtcpPacketRemb {
- int64_t timestamp_us;
- rtcp::Remb remb;
- int64_t log_time_us() const { return timestamp_us; }
- int64_t log_time_ms() const { return timestamp_us / 1000; }
-};
-
-struct LoggedRtcpPacketNack {
- int64_t timestamp_us;
- rtcp::Nack nack;
- int64_t log_time_us() const { return timestamp_us; }
- int64_t log_time_ms() const { return timestamp_us / 1000; }
-};
-
-struct LoggedRtcpPacketTransportFeedback {
- int64_t timestamp_us;
- rtcp::TransportFeedback transport_feedback;
- int64_t log_time_us() const { return timestamp_us; }
- int64_t log_time_ms() const { return timestamp_us / 1000; }
-};
-
-struct LoggedStartEvent {
- explicit LoggedStartEvent(uint64_t timestamp_us)
- : timestamp_us(timestamp_us) {}
- int64_t timestamp_us;
- int64_t log_time_us() const { return timestamp_us; }
- int64_t log_time_ms() const { return timestamp_us / 1000; }
-};
-
-struct LoggedStopEvent {
- explicit LoggedStopEvent(uint64_t timestamp_us)
- : timestamp_us(timestamp_us) {}
- int64_t timestamp_us;
- int64_t log_time_us() const { return timestamp_us; }
- int64_t log_time_ms() const { return timestamp_us / 1000; }
-};
-
-struct LoggedAudioRecvConfig {
- LoggedAudioRecvConfig(int64_t timestamp_us, const rtclog::StreamConfig config)
- : timestamp_us(timestamp_us), config(config) {}
- int64_t timestamp_us;
- rtclog::StreamConfig config;
- int64_t log_time_us() const { return timestamp_us; }
- int64_t log_time_ms() const { return timestamp_us / 1000; }
-};
-
-struct LoggedAudioSendConfig {
- LoggedAudioSendConfig(int64_t timestamp_us, const rtclog::StreamConfig config)
- : timestamp_us(timestamp_us), config(config) {}
- int64_t timestamp_us;
- rtclog::StreamConfig config;
- int64_t log_time_us() const { return timestamp_us; }
- int64_t log_time_ms() const { return timestamp_us / 1000; }
-};
-
-struct LoggedVideoRecvConfig {
- LoggedVideoRecvConfig(int64_t timestamp_us, const rtclog::StreamConfig config)
- : timestamp_us(timestamp_us), config(config) {}
- int64_t timestamp_us;
- rtclog::StreamConfig config;
- int64_t log_time_us() const { return timestamp_us; }
- int64_t log_time_ms() const { return timestamp_us / 1000; }
-};
-
-struct LoggedVideoSendConfig {
- LoggedVideoSendConfig(int64_t timestamp_us,
- const std::vector<rtclog::StreamConfig> configs)
- : timestamp_us(timestamp_us), configs(configs) {}
- int64_t timestamp_us;
- std::vector<rtclog::StreamConfig> configs;
- int64_t log_time_us() const { return timestamp_us; }
- int64_t log_time_ms() const { return timestamp_us / 1000; }
-};
-
-template <typename T>
-class PacketView;
-
-template <typename T>
-class PacketIterator {
- friend class PacketView<T>;
-
- public:
- // Standard iterator traits.
- using difference_type = std::ptrdiff_t;
- using value_type = T;
- using pointer = T*;
- using reference = T&;
- using iterator_category = std::bidirectional_iterator_tag;
-
- // The default-contructed iterator is meaningless, but is required by the
- // ForwardIterator concept.
- PacketIterator() : ptr_(nullptr), element_size_(0) {}
- PacketIterator(const PacketIterator& other)
- : ptr_(other.ptr_), element_size_(other.element_size_) {}
- PacketIterator(const PacketIterator&& other)
- : ptr_(other.ptr_), element_size_(other.element_size_) {}
- ~PacketIterator() = default;
-
- PacketIterator& operator=(const PacketIterator& other) {
- ptr_ = other.ptr_;
- element_size_ = other.element_size_;
- return *this;
- }
- PacketIterator& operator=(const PacketIterator&& other) {
- ptr_ = other.ptr_;
- element_size_ = other.element_size_;
- return *this;
- }
-
- bool operator==(const PacketIterator<T>& other) const {
- RTC_DCHECK_EQ(element_size_, other.element_size_);
- return ptr_ == other.ptr_;
- }
- bool operator!=(const PacketIterator<T>& other) const {
- RTC_DCHECK_EQ(element_size_, other.element_size_);
- return ptr_ != other.ptr_;
- }
-
- PacketIterator& operator++() {
- ptr_ += element_size_;
- return *this;
- }
- PacketIterator& operator--() {
- ptr_ -= element_size_;
- return *this;
- }
- PacketIterator operator++(int) {
- PacketIterator iter_copy(ptr_, element_size_);
- ptr_ += element_size_;
- return iter_copy;
- }
- PacketIterator operator--(int) {
- PacketIterator iter_copy(ptr_, element_size_);
- ptr_ -= element_size_;
- return iter_copy;
- }
-
- T& operator*() { return *reinterpret_cast<T*>(ptr_); }
- const T& operator*() const { return *reinterpret_cast<const T*>(ptr_); }
-
- private:
- PacketIterator(typename std::conditional<std::is_const<T>::value,
- const void*,
- void*>::type p,
- size_t s)
- : ptr_(reinterpret_cast<decltype(ptr_)>(p)), element_size_(s) {}
-
- typename std::conditional<std::is_const<T>::value, const char*, char*>::type
- ptr_;
- size_t element_size_;
-};
-
-// Suppose that we have a struct S where we are only interested in a specific
-// member M. Given an array of S, PacketView can be used to treat the array
-// as an array of M, without exposing the type S to surrounding code and without
-// accessing the member through a virtual function. In this case, we want to
-// have a common view for incoming and outgoing RtpPackets, hence the PacketView
-// name.
-// Note that constructing a PacketView bypasses the typesystem, so the caller
-// has to take extra care when constructing these objects. The implementation
-// also requires that the containing struct is standard-layout (e.g. POD).
-//
-// Usage example:
-// struct A {...};
-// struct B { A a; ...};
-// struct C { A a; ...};
-// size_t len = 10;
-// B* array1 = new B[len];
-// C* array2 = new C[len];
-//
-// PacketView<A> view1 = PacketView<A>::Create<B>(array1, len, offsetof(B, a));
-// PacketView<A> view2 = PacketView<A>::Create<C>(array2, len, offsetof(C, a));
-//
-// The following code works with either view1 or view2.
-// void f(PacketView<A> view)
-// for (A& a : view) {
-// DoSomething(a);
-// }
-template <typename T>
-class PacketView {
- public:
- template <typename U>
- static PacketView Create(U* ptr, size_t num_elements, size_t offset) {
- static_assert(std::is_standard_layout<U>::value,
- "PacketView can only be created for standard layout types.");
- static_assert(std::is_standard_layout<T>::value,
- "PacketView can only be created for standard layout types.");
- return PacketView(ptr, num_elements, offset, sizeof(U));
- }
-
- using iterator = PacketIterator<T>;
- using const_iterator = PacketIterator<const T>;
- using reverse_iterator = std::reverse_iterator<iterator>;
- using const_reverse_iterator = std::reverse_iterator<const_iterator>;
-
- iterator begin() { return iterator(data_, element_size_); }
- iterator end() {
- auto end_ptr = data_ + num_elements_ * element_size_;
- return iterator(end_ptr, element_size_);
- }
-
- const_iterator begin() const { return const_iterator(data_, element_size_); }
- const_iterator end() const {
- auto end_ptr = data_ + num_elements_ * element_size_;
- return const_iterator(end_ptr, element_size_);
- }
-
- reverse_iterator rbegin() { return reverse_iterator(end()); }
- reverse_iterator rend() { return reverse_iterator(begin()); }
-
- const_reverse_iterator rbegin() const {
- return const_reverse_iterator(end());
- }
- const_reverse_iterator rend() const {
- return const_reverse_iterator(begin());
- }
-
- size_t size() const { return num_elements_; }
-
- T& operator[](size_t i) {
- auto elem_ptr = data_ + i * element_size_;
- return *reinterpret_cast<T*>(elem_ptr);
- }
-
- const T& operator[](size_t i) const {
- auto elem_ptr = data_ + i * element_size_;
- return *reinterpret_cast<const T*>(elem_ptr);
- }
-
- private:
- PacketView(typename std::conditional<std::is_const<T>::value,
- const void*,
- void*>::type data,
- size_t num_elements,
- size_t offset,
- size_t element_size)
- : data_(reinterpret_cast<decltype(data_)>(data) + offset),
- num_elements_(num_elements),
- element_size_(element_size) {}
-
- typename std::conditional<std::is_const<T>::value, const char*, char*>::type
- data_;
- size_t num_elements_;
- size_t element_size_;
-};
-
-class ParsedRtcEventLog {
- friend class RtcEventLogTestHelper;
-
- public:
- enum EventType {
- UNKNOWN_EVENT = 0,
- LOG_START = 1,
- LOG_END = 2,
- RTP_EVENT = 3,
- RTCP_EVENT = 4,
- AUDIO_PLAYOUT_EVENT = 5,
- LOSS_BASED_BWE_UPDATE = 6,
- DELAY_BASED_BWE_UPDATE = 7,
- VIDEO_RECEIVER_CONFIG_EVENT = 8,
- VIDEO_SENDER_CONFIG_EVENT = 9,
- AUDIO_RECEIVER_CONFIG_EVENT = 10,
- AUDIO_SENDER_CONFIG_EVENT = 11,
- AUDIO_NETWORK_ADAPTATION_EVENT = 16,
- 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,
- };
-
- enum class MediaType { ANY, AUDIO, VIDEO, DATA };
- enum class UnconfiguredHeaderExtensions {
- kDontParse,
- kAttemptWebrtcDefaultConfig
- };
-
- explicit ParsedRtcEventLog(
- UnconfiguredHeaderExtensions parse_unconfigured_header_extensions =
- UnconfiguredHeaderExtensions::kDontParse);
-
- // Clears previously parsed events and resets the ParsedRtcEventLog to an
- // empty state.
- void Clear();
-
- // Reads an RtcEventLog file and returns true if parsing was successful.
- bool ParseFile(const std::string& file_name);
-
- // Reads an RtcEventLog from a string and returns true if successful.
- bool ParseString(const std::string& s);
-
- // Reads an RtcEventLog from an istream and returns true if successful.
- bool ParseStream(
- std::istream& stream); // no-presubmit-check TODO(webrtc:8982)
-
- // Returns the number of events in an EventStream.
- size_t GetNumberOfEvents() const;
-
- // Reads the arrival timestamp (in microseconds) from a rtclog::Event.
- int64_t GetTimestamp(size_t index) const;
- int64_t GetTimestamp(const rtclog::Event& event) const;
-
- // Reads the event type of the rtclog::Event at |index|.
- EventType GetEventType(size_t index) const;
-
- // Reads the header, direction, header length and packet length from the RTP
- // event at |index|, and stores the values in the corresponding output
- // parameters. Each output parameter can be set to nullptr if that value
- // isn't needed.
- // NB: The header must have space for at least IP_PACKET_SIZE bytes.
- // Returns: a pointer to a header extensions map acquired from parsing
- // corresponding Audio/Video Sender/Receiver config events.
- // Warning: if the same SSRC is reused by both video and audio streams during
- // call, extensions maps may be incorrect (the last one would be returned).
- const webrtc::RtpHeaderExtensionMap* GetRtpHeader(
- size_t index,
- PacketDirection* incoming,
- uint8_t* header,
- size_t* header_length,
- size_t* total_length,
- int* probe_cluster_id) const;
- const webrtc::RtpHeaderExtensionMap* GetRtpHeader(
- const rtclog::Event& event,
- PacketDirection* incoming,
- uint8_t* header,
- size_t* header_length,
- size_t* total_length,
- int* probe_cluster_id) const;
-
- // Reads packet, direction and packet length from the RTCP event at |index|,
- // and stores the values in the corresponding output parameters.
- // Each output parameter can be set to nullptr if that value isn't needed.
- // NB: The packet must have space for at least IP_PACKET_SIZE bytes.
- void GetRtcpPacket(size_t index,
- PacketDirection* incoming,
- uint8_t* packet,
- size_t* length) const;
- void GetRtcpPacket(const rtclog::Event& event,
- PacketDirection* incoming,
- uint8_t* packet,
- size_t* length) const;
-
- // Reads a video receive config event to a StreamConfig struct.
- // Only the fields that are stored in the protobuf will be written.
- rtclog::StreamConfig GetVideoReceiveConfig(size_t index) const;
-
- // Reads a video send config event to a StreamConfig struct. If the proto
- // contains multiple SSRCs and RTX SSRCs (this used to be the case for
- // simulcast streams) then we return one StreamConfig per SSRC,RTX_SSRC pair.
- // Only the fields that are stored in the protobuf will be written.
- std::vector<rtclog::StreamConfig> GetVideoSendConfig(size_t index) const;
-
- // Reads a audio receive config event to a StreamConfig struct.
- // Only the fields that are stored in the protobuf will be written.
- rtclog::StreamConfig GetAudioReceiveConfig(size_t index) const;
-
- // Reads a config event to a StreamConfig struct.
- // Only the fields that are stored in the protobuf will be written.
- rtclog::StreamConfig GetAudioSendConfig(size_t index) const;
-
- // Reads the SSRC from the audio playout event at |index|. The SSRC is stored
- // in the output parameter ssrc. The output parameter can be set to nullptr
- // and in that case the function only asserts that the event is well formed.
- LoggedAudioPlayoutEvent GetAudioPlayout(size_t index) const;
-
- // Reads bitrate, fraction loss (as defined in RFC 1889) and total number of
- // expected packets from the loss based BWE event at |index| and stores the
- // values in
- // the corresponding output parameters. Each output parameter can be set to
- // nullptr if that
- // value isn't needed.
- LoggedBweLossBasedUpdate GetLossBasedBweUpdate(size_t index) const;
-
- // Reads bitrate and detector_state from the delay based BWE event at |index|
- // and stores the values in the corresponding output parameters. Each output
- // parameter can be set to nullptr if that
- // value isn't needed.
- LoggedBweDelayBasedUpdate GetDelayBasedBweUpdate(size_t index) const;
-
- // Reads a audio network adaptation event to a (non-NULL)
- // AudioEncoderRuntimeConfig struct. Only the fields that are
- // stored in the protobuf will be written.
- LoggedAudioNetworkAdaptationEvent GetAudioNetworkAdaptation(
- size_t index) const;
-
- LoggedBweProbeClusterCreatedEvent GetBweProbeClusterCreated(
- size_t index) const;
-
- LoggedBweProbeResultEvent GetBweProbeResult(size_t index) const;
-
- MediaType GetMediaType(uint32_t ssrc, PacketDirection direction) const;
-
- LoggedAlrStateEvent GetAlrState(size_t index) const;
-
- LoggedIceCandidatePairConfig GetIceCandidatePairConfig(size_t index) const;
-
- LoggedIceCandidatePairEvent GetIceCandidatePairEvent(size_t index) const;
-
- const std::set<uint32_t>& incoming_rtx_ssrcs() const {
- return incoming_rtx_ssrcs_;
- }
- const std::set<uint32_t>& incoming_video_ssrcs() const {
- return incoming_video_ssrcs_;
- }
- const std::set<uint32_t>& incoming_audio_ssrcs() const {
- return incoming_audio_ssrcs_;
- }
- const std::set<uint32_t>& outgoing_rtx_ssrcs() const {
- return outgoing_rtx_ssrcs_;
- }
- const std::set<uint32_t>& outgoing_video_ssrcs() const {
- return outgoing_video_ssrcs_;
- }
- const std::set<uint32_t>& outgoing_audio_ssrcs() const {
- return outgoing_audio_ssrcs_;
- }
-
- const std::vector<LoggedStartEvent>& start_log_events() const {
- return start_log_events_;
- }
- const std::vector<LoggedStopEvent>& stop_log_events() const {
- return stop_log_events_;
- }
- const std::map<uint32_t, std::vector<int64_t>>& audio_playout_events() const {
- return audio_playout_events_;
- }
- const std::vector<LoggedAudioNetworkAdaptationEvent>&
- audio_network_adaptation_events() const {
- return audio_network_adaptation_events_;
- }
- const std::vector<LoggedBweProbeClusterCreatedEvent>&
- bwe_probe_cluster_created_events() const {
- return bwe_probe_cluster_created_events_;
- }
- const std::vector<LoggedBweProbeResultEvent>& bwe_probe_result_events()
- const {
- return bwe_probe_result_events_;
- }
- const std::vector<LoggedBweDelayBasedUpdate>& bwe_delay_updates() const {
- return bwe_delay_updates_;
- }
- const std::vector<LoggedBweLossBasedUpdate>& bwe_loss_updates() const {
- return bwe_loss_updates_;
- }
- const std::vector<LoggedAlrStateEvent>& alr_state_events() const {
- return alr_state_events_;
- }
- const std::vector<LoggedIceCandidatePairConfig>& ice_candidate_pair_configs()
- const {
- return ice_candidate_pair_configs_;
- }
- const std::vector<LoggedIceCandidatePairEvent>& ice_candidate_pair_events()
- const {
- return ice_candidate_pair_events_;
- }
-
- struct LoggedRtpStreamIncoming {
- uint32_t ssrc;
- std::vector<LoggedRtpPacketIncoming> incoming_packets;
- };
-
- struct LoggedRtpStreamOutgoing {
- uint32_t ssrc;
- std::vector<LoggedRtpPacketOutgoing> outgoing_packets;
- };
-
- struct LoggedRtpStreamView {
- LoggedRtpStreamView(uint32_t ssrc,
- const LoggedRtpPacketIncoming* ptr,
- size_t num_elements)
- : ssrc(ssrc),
- packet_view(PacketView<const LoggedRtpPacket>::Create(
- ptr,
- num_elements,
- offsetof(LoggedRtpPacketIncoming, rtp))) {}
- LoggedRtpStreamView(uint32_t ssrc,
- const LoggedRtpPacketOutgoing* ptr,
- size_t num_elements)
- : ssrc(ssrc),
- packet_view(PacketView<const LoggedRtpPacket>::Create(
- ptr,
- num_elements,
- offsetof(LoggedRtpPacketOutgoing, rtp))) {}
- uint32_t ssrc;
- PacketView<const LoggedRtpPacket> packet_view;
- };
-
- const std::vector<LoggedRtpStreamIncoming>& incoming_rtp_packets_by_ssrc()
- const {
- return incoming_rtp_packets_by_ssrc_;
- }
-
- const std::vector<LoggedRtpStreamOutgoing>& outgoing_rtp_packets_by_ssrc()
- const {
- return outgoing_rtp_packets_by_ssrc_;
- }
-
- const std::vector<LoggedRtcpPacketIncoming>& incoming_rtcp_packets() const {
- return incoming_rtcp_packets_;
- }
-
- const std::vector<LoggedRtcpPacketOutgoing>& outgoing_rtcp_packets() const {
- return outgoing_rtcp_packets_;
- }
-
- const std::vector<LoggedRtpStreamView>& rtp_packets_by_ssrc(
- PacketDirection direction) const {
- if (direction == kIncomingPacket)
- return incoming_rtp_packet_views_by_ssrc_;
- else
- return outgoing_rtp_packet_views_by_ssrc_;
- }
-
- const std::vector<LoggedRtcpPacketReceiverReport>& receiver_reports(
- PacketDirection direction) const {
- if (direction == kIncomingPacket) {
- return incoming_rr_;
- } else {
- return outgoing_rr_;
- }
- }
-
- const std::vector<LoggedRtcpPacketSenderReport>& sender_reports(
- PacketDirection direction) const {
- if (direction == kIncomingPacket) {
- return incoming_sr_;
- } else {
- return outgoing_sr_;
- }
- }
-
- const std::vector<LoggedRtcpPacketNack>& nacks(
- PacketDirection direction) const {
- if (direction == kIncomingPacket) {
- return incoming_nack_;
- } else {
- return outgoing_nack_;
- }
- }
-
- const std::vector<LoggedRtcpPacketRemb>& rembs(
- PacketDirection direction) const {
- if (direction == kIncomingPacket) {
- return incoming_remb_;
- } else {
- return outgoing_remb_;
- }
- }
-
- const std::vector<LoggedRtcpPacketTransportFeedback>& transport_feedbacks(
- PacketDirection direction) const {
- if (direction == kIncomingPacket) {
- return incoming_transport_feedback_;
- } else {
- return outgoing_transport_feedback_;
- }
- }
-
- int64_t first_timestamp() const { return first_timestamp_; }
- int64_t last_timestamp() const { return last_timestamp_; }
-
- private:
- void StoreParsedEvent(const rtclog::Event& event);
-
- rtclog::StreamConfig GetVideoReceiveConfig(const rtclog::Event& event) const;
- std::vector<rtclog::StreamConfig> GetVideoSendConfig(
- const rtclog::Event& event) const;
- rtclog::StreamConfig GetAudioReceiveConfig(const rtclog::Event& event) const;
- rtclog::StreamConfig GetAudioSendConfig(const rtclog::Event& event) const;
-
- LoggedAudioPlayoutEvent GetAudioPlayout(const rtclog::Event& event) const;
-
- LoggedBweLossBasedUpdate GetLossBasedBweUpdate(
- const rtclog::Event& event) const;
- LoggedBweDelayBasedUpdate GetDelayBasedBweUpdate(
- const rtclog::Event& event) const;
-
- LoggedAudioNetworkAdaptationEvent GetAudioNetworkAdaptation(
- const rtclog::Event& event) const;
-
- LoggedBweProbeClusterCreatedEvent GetBweProbeClusterCreated(
- const rtclog::Event& event) const;
- LoggedBweProbeResultEvent GetBweProbeResult(const rtclog::Event& event) const;
-
- LoggedAlrStateEvent GetAlrState(const rtclog::Event& event) const;
-
- LoggedIceCandidatePairConfig GetIceCandidatePairConfig(
- const rtclog::Event& event) const;
- LoggedIceCandidatePairEvent GetIceCandidatePairEvent(
- const rtclog::Event& event) const;
-
- std::vector<rtclog::Event> events_;
-
- struct Stream {
- Stream(uint32_t ssrc,
- MediaType media_type,
- PacketDirection direction,
- webrtc::RtpHeaderExtensionMap map)
- : ssrc(ssrc),
- media_type(media_type),
- direction(direction),
- rtp_extensions_map(map) {}
- uint32_t ssrc;
- MediaType media_type;
- PacketDirection direction;
- webrtc::RtpHeaderExtensionMap rtp_extensions_map;
- };
-
- const UnconfiguredHeaderExtensions parse_unconfigured_header_extensions_;
-
- // Make a default extension map for streams without configuration information.
- // TODO(ivoc): Once configuration of audio streams is stored in the event log,
- // this can be removed. Tracking bug: webrtc:6399
- RtpHeaderExtensionMap default_extension_map_;
-
- // Tracks what each stream is configured for. Note that a single SSRC can be
- // in several sets. For example, the SSRC used for sending video over RTX
- // will appear in both video_ssrcs_ and rtx_ssrcs_. In the unlikely case that
- // an SSRC is reconfigured to a different media type mid-call, it will also
- // appear in multiple sets.
- std::set<uint32_t> incoming_rtx_ssrcs_;
- std::set<uint32_t> incoming_video_ssrcs_;
- std::set<uint32_t> incoming_audio_ssrcs_;
- std::set<uint32_t> outgoing_rtx_ssrcs_;
- std::set<uint32_t> outgoing_video_ssrcs_;
- std::set<uint32_t> outgoing_audio_ssrcs_;
-
- // Maps an SSRC to the parsed RTP headers in that stream. Header extensions
- // are parsed if the stream has been configured. This is only used for
- // grouping the events by SSRC during parsing; the events are moved to
- // incoming_rtp_packets_by_ssrc_ once the parsing is done.
- std::map<uint32_t, std::vector<LoggedRtpPacketIncoming>>
- incoming_rtp_packets_map_;
- std::map<uint32_t, std::vector<LoggedRtpPacketOutgoing>>
- outgoing_rtp_packets_map_;
-
- // RTP headers.
- std::vector<LoggedRtpStreamIncoming> incoming_rtp_packets_by_ssrc_;
- std::vector<LoggedRtpStreamOutgoing> outgoing_rtp_packets_by_ssrc_;
- std::vector<LoggedRtpStreamView> incoming_rtp_packet_views_by_ssrc_;
- std::vector<LoggedRtpStreamView> outgoing_rtp_packet_views_by_ssrc_;
-
- // Raw RTCP packets.
- std::vector<LoggedRtcpPacketIncoming> incoming_rtcp_packets_;
- std::vector<LoggedRtcpPacketOutgoing> outgoing_rtcp_packets_;
-
- // Parsed RTCP messages. Currently not separated based on SSRC.
- std::vector<LoggedRtcpPacketReceiverReport> incoming_rr_;
- std::vector<LoggedRtcpPacketReceiverReport> outgoing_rr_;
- std::vector<LoggedRtcpPacketSenderReport> incoming_sr_;
- std::vector<LoggedRtcpPacketSenderReport> outgoing_sr_;
- std::vector<LoggedRtcpPacketNack> incoming_nack_;
- std::vector<LoggedRtcpPacketNack> outgoing_nack_;
- std::vector<LoggedRtcpPacketRemb> incoming_remb_;
- std::vector<LoggedRtcpPacketRemb> outgoing_remb_;
- std::vector<LoggedRtcpPacketTransportFeedback> incoming_transport_feedback_;
- std::vector<LoggedRtcpPacketTransportFeedback> outgoing_transport_feedback_;
-
- std::vector<LoggedStartEvent> start_log_events_;
- std::vector<LoggedStopEvent> stop_log_events_;
-
- // Maps an SSRC to the timestamps of parsed audio playout events.
- std::map<uint32_t, std::vector<int64_t>> audio_playout_events_;
-
- std::vector<LoggedAudioNetworkAdaptationEvent>
- audio_network_adaptation_events_;
-
- std::vector<LoggedBweProbeClusterCreatedEvent>
- bwe_probe_cluster_created_events_;
-
- std::vector<LoggedBweProbeResultEvent> bwe_probe_result_events_;
-
- std::vector<LoggedBweDelayBasedUpdate> bwe_delay_updates_;
-
- // A list of all updates from the send-side loss-based bandwidth estimator.
- std::vector<LoggedBweLossBasedUpdate> bwe_loss_updates_;
-
- std::vector<LoggedAlrStateEvent> alr_state_events_;
-
- std::vector<LoggedIceCandidatePairConfig> ice_candidate_pair_configs_;
-
- std::vector<LoggedIceCandidatePairEvent> ice_candidate_pair_events_;
-
- std::vector<LoggedAudioRecvConfig> audio_recv_configs_;
- std::vector<LoggedAudioSendConfig> audio_send_configs_;
- std::vector<LoggedVideoRecvConfig> video_recv_configs_;
- std::vector<LoggedVideoSendConfig> video_send_configs_;
-
- uint8_t last_incoming_rtcp_packet_[IP_PACKET_SIZE];
- uint8_t last_incoming_rtcp_packet_length_;
-
- int64_t first_timestamp_;
- int64_t last_timestamp_;
-
- // The extension maps are mutable to allow us to insert the default
- // configuration when parsing an RTP header for an unconfigured stream.
- mutable std::map<uint32_t, webrtc::RtpHeaderExtensionMap>
- incoming_rtp_extensions_maps_;
- mutable std::map<uint32_t, webrtc::RtpHeaderExtensionMap>
- outgoing_rtp_extensions_maps_;
-};
-
-} // namespace webrtc
-
-#endif // LOGGING_RTC_EVENT_LOG_RTC_EVENT_LOG_PARSER2_H_
diff --git a/logging/rtc_event_log/rtc_event_log_unittest.cc b/logging/rtc_event_log/rtc_event_log_unittest.cc
index 529228b..1cea313 100644
--- a/logging/rtc_event_log/rtc_event_log_unittest.cc
+++ b/logging/rtc_event_log/rtc_event_log_unittest.cc
@@ -34,7 +34,7 @@
#include "logging/rtc_event_log/events/rtc_event_video_send_stream_config.h"
#include "logging/rtc_event_log/output/rtc_event_log_output_file.h"
#include "logging/rtc_event_log/rtc_event_log.h"
-#include "logging/rtc_event_log/rtc_event_log_parser2.h"
+#include "logging/rtc_event_log/rtc_event_log_parser.h"
#include "logging/rtc_event_log/rtc_event_log_unittest_helper.h"
#include "logging/rtc_event_log/rtc_stream_config.h"
#include "modules/audio_coding/audio_network_adaptor/include/audio_network_adaptor.h"
@@ -750,16 +750,17 @@
for (size_t i = 1; i < parsed_log.GetNumberOfEvents() - 1; i++) {
EXPECT_EQ(parsed_log.GetEventType(i),
ParsedRtcEventLog::EventType::AUDIO_PLAYOUT_EVENT);
- LoggedAudioPlayoutEvent playout_event = parsed_log.GetAudioPlayout(i);
- EXPECT_LT(playout_event.ssrc, kNumEvents);
- EXPECT_EQ(static_cast<int64_t>(kStartTime + 10000 * playout_event.ssrc),
- playout_event.timestamp_us);
+ uint32_t ssrc;
+ parsed_log.GetAudioPlayout(i, &ssrc);
+ int64_t timestamp = parsed_log.GetTimestamp(i);
+ EXPECT_LT(ssrc, kNumEvents);
+ EXPECT_EQ(static_cast<int64_t>(kStartTime + 10000 * ssrc), timestamp);
if (last_ssrc)
- EXPECT_EQ(playout_event.ssrc, *last_ssrc + 1);
+ EXPECT_EQ(ssrc, *last_ssrc + 1);
if (last_timestamp)
- EXPECT_EQ(playout_event.timestamp_us, *last_timestamp + 10000);
- last_ssrc = playout_event.ssrc;
- last_timestamp = playout_event.timestamp_us;
+ EXPECT_EQ(timestamp, *last_timestamp + 10000);
+ last_ssrc = ssrc;
+ last_timestamp = timestamp;
}
RtcEventLogTestHelper::VerifyLogEndEvent(parsed_log,
parsed_log.GetNumberOfEvents() - 1);
diff --git a/logging/rtc_event_log/rtc_event_log_unittest_helper.cc b/logging/rtc_event_log/rtc_event_log_unittest_helper.cc
index 955c3b9..23e15b5 100644
--- a/logging/rtc_event_log/rtc_event_log_unittest_helper.cc
+++ b/logging/rtc_event_log/rtc_event_log_unittest_helper.cc
@@ -460,8 +460,9 @@
EXPECT_EQ(ssrc, playout_event.local_ssrc());
// Check consistency of the parser.
- LoggedAudioPlayoutEvent parsed_event = parsed_log.GetAudioPlayout(index);
- EXPECT_EQ(ssrc, parsed_event.ssrc);
+ uint32_t parsed_ssrc;
+ parsed_log.GetAudioPlayout(index, &parsed_ssrc);
+ EXPECT_EQ(ssrc, parsed_ssrc);
}
void RtcEventLogTestHelper::VerifyBweLossEvent(
@@ -483,10 +484,14 @@
EXPECT_EQ(total_packets, bwe_event.total_packets());
// Check consistency of the parser.
- LoggedBweLossBasedUpdate bwe_update = parsed_log.GetLossBasedBweUpdate(index);
- EXPECT_EQ(bitrate, bwe_update.bitrate_bps);
- EXPECT_EQ(fraction_loss, bwe_update.fraction_lost);
- EXPECT_EQ(total_packets, bwe_update.expected_packets);
+ int32_t parsed_bitrate;
+ uint8_t parsed_fraction_loss;
+ int32_t parsed_total_packets;
+ parsed_log.GetLossBasedBweUpdate(
+ index, &parsed_bitrate, &parsed_fraction_loss, &parsed_total_packets);
+ EXPECT_EQ(bitrate, parsed_bitrate);
+ EXPECT_EQ(fraction_loss, parsed_fraction_loss);
+ EXPECT_EQ(total_packets, parsed_total_packets);
}
void RtcEventLogTestHelper::VerifyBweDelayEvent(
@@ -506,7 +511,8 @@
GetRuntimeDetectorState(bwe_event.detector_state()));
// Check consistency of the parser.
- LoggedBweDelayBasedUpdate res = parsed_log.GetDelayBasedBweUpdate(index);
+ ParsedRtcEventLog::BweDelayBasedUpdate res =
+ parsed_log.GetDelayBasedBweUpdate(index);
EXPECT_EQ(res.bitrate_bps, bitrate);
EXPECT_EQ(res.detector_state, detector_state);
}
@@ -515,20 +521,15 @@
const ParsedRtcEventLog& parsed_log,
size_t index,
const AudioEncoderRuntimeConfig& config) {
- ASSERT_LT(index, parsed_log.events_.size());
- const rtclog::Event& event = parsed_log.events_[index];
- ASSERT_TRUE(IsValidBasicEvent(event));
- ASSERT_EQ(rtclog::Event::AUDIO_NETWORK_ADAPTATION_EVENT, event.type());
-
- LoggedAudioNetworkAdaptationEvent parsed_event =
- parsed_log.GetAudioNetworkAdaptation(index);
- EXPECT_EQ(config.bitrate_bps, parsed_event.config.bitrate_bps);
- EXPECT_EQ(config.enable_dtx, parsed_event.config.enable_dtx);
- EXPECT_EQ(config.enable_fec, parsed_event.config.enable_fec);
- EXPECT_EQ(config.frame_length_ms, parsed_event.config.frame_length_ms);
- EXPECT_EQ(config.num_channels, parsed_event.config.num_channels);
+ AudioEncoderRuntimeConfig parsed_config;
+ parsed_log.GetAudioNetworkAdaptation(index, &parsed_config);
+ EXPECT_EQ(config.bitrate_bps, parsed_config.bitrate_bps);
+ EXPECT_EQ(config.enable_dtx, parsed_config.enable_dtx);
+ EXPECT_EQ(config.enable_fec, parsed_config.enable_fec);
+ EXPECT_EQ(config.frame_length_ms, parsed_config.frame_length_ms);
+ EXPECT_EQ(config.num_channels, parsed_config.num_channels);
EXPECT_EQ(config.uplink_packet_loss_fraction,
- parsed_event.config.uplink_packet_loss_fraction);
+ parsed_config.uplink_packet_loss_fraction);
}
void RtcEventLogTestHelper::VerifyLogStartEvent(
diff --git a/logging/rtc_event_log/rtc_event_log_unittest_helper.h b/logging/rtc_event_log/rtc_event_log_unittest_helper.h
index 949a3db..630f160 100644
--- a/logging/rtc_event_log/rtc_event_log_unittest_helper.h
+++ b/logging/rtc_event_log/rtc_event_log_unittest_helper.h
@@ -12,7 +12,7 @@
#define LOGGING_RTC_EVENT_LOG_RTC_EVENT_LOG_UNITTEST_HELPER_H_
#include "call/call.h"
-#include "logging/rtc_event_log/rtc_event_log_parser2.h"
+#include "logging/rtc_event_log/rtc_event_log_parser.h"
#include "modules/rtp_rtcp/source/rtp_packet_received.h"
#include "modules/rtp_rtcp/source/rtp_packet_to_send.h"
diff --git a/modules/audio_coding/neteq/tools/rtc_event_log_source.cc b/modules/audio_coding/neteq/tools/rtc_event_log_source.cc
index b370e88..d6224ff 100644
--- a/modules/audio_coding/neteq/tools/rtc_event_log_source.cc
+++ b/modules/audio_coding/neteq/tools/rtc_event_log_source.cc
@@ -66,7 +66,7 @@
}
if (parsed_stream_.GetMediaType(packet->header().ssrc, direction) !=
- ParsedRtcEventLog::MediaType::AUDIO) {
+ webrtc::ParsedRtcEventLog::MediaType::AUDIO) {
continue;
}
@@ -85,10 +85,12 @@
while (audio_output_index_ < parsed_stream_.GetNumberOfEvents()) {
if (parsed_stream_.GetEventType(audio_output_index_) ==
ParsedRtcEventLog::AUDIO_PLAYOUT_EVENT) {
- LoggedAudioPlayoutEvent playout_event =
- parsed_stream_.GetAudioPlayout(audio_output_index_);
+ uint64_t timestamp_us = parsed_stream_.GetTimestamp(audio_output_index_);
+ // We call GetAudioPlayout only to check that the protobuf event is
+ // well-formed.
+ parsed_stream_.GetAudioPlayout(audio_output_index_, nullptr);
audio_output_index_++;
- return playout_event.timestamp_us / 1000;
+ return timestamp_us / 1000;
}
audio_output_index_++;
}
diff --git a/modules/audio_coding/neteq/tools/rtc_event_log_source.h b/modules/audio_coding/neteq/tools/rtc_event_log_source.h
index 1b25e12..df01e06 100644
--- a/modules/audio_coding/neteq/tools/rtc_event_log_source.h
+++ b/modules/audio_coding/neteq/tools/rtc_event_log_source.h
@@ -14,7 +14,7 @@
#include <memory>
#include <string>
-#include "logging/rtc_event_log/rtc_event_log_parser2.h"
+#include "logging/rtc_event_log/rtc_event_log_parser.h"
#include "modules/audio_coding/neteq/tools/packet_source.h"
#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
#include "rtc_base/constructormagic.h"
diff --git a/rtc_tools/BUILD.gn b/rtc_tools/BUILD.gn
index 73e2494..d1d2b55 100644
--- a/rtc_tools/BUILD.gn
+++ b/rtc_tools/BUILD.gn
@@ -237,7 +237,6 @@
"../rtc_base:checks",
"../rtc_base:rtc_base_approved",
"../rtc_base:rtc_numerics",
- "../rtc_base:stringutils",
# TODO(kwiberg): Remove this dependency.
"../api/audio_codecs:audio_codecs_api",
diff --git a/rtc_tools/event_log_visualizer/analyzer.cc b/rtc_tools/event_log_visualizer/analyzer.cc
index c780632..1a7309c 100644
--- a/rtc_tools/event_log_visualizer/analyzer.cc
+++ b/rtc_tools/event_log_visualizer/analyzer.cc
@@ -14,6 +14,7 @@
#include <cmath>
#include <limits>
#include <map>
+#include <sstream>
#include <string>
#include <utility>
@@ -24,7 +25,6 @@
#include "call/video_send_stream.h"
#include "common_types.h" // NOLINT(build/include)
#include "logging/rtc_event_log/rtc_stream_config.h"
-#include "modules/audio_coding/audio_network_adaptor/include/audio_network_adaptor.h"
#include "modules/audio_coding/neteq/tools/audio_sink.h"
#include "modules/audio_coding/neteq/tools/fake_decode_from_file.h"
#include "modules/audio_coding/neteq/tools/neteq_delay_analyzer.h"
@@ -40,7 +40,6 @@
#include "modules/pacing/packet_router.h"
#include "modules/rtp_rtcp/include/rtp_rtcp.h"
#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
-#include "modules/rtp_rtcp/source/rtcp_packet.h"
#include "modules/rtp_rtcp/source/rtcp_packet/common_header.h"
#include "modules/rtp_rtcp/source/rtcp_packet/receiver_report.h"
#include "modules/rtp_rtcp/source/rtcp_packet/remb.h"
@@ -50,7 +49,6 @@
#include "modules/rtp_rtcp/source/rtp_utility.h"
#include "rtc_base/checks.h"
#include "rtc_base/format_macros.h"
-#include "rtc_base/function_view.h"
#include "rtc_base/logging.h"
#include "rtc_base/numerics/sequence_number_util.h"
#include "rtc_base/ptr_util.h"
@@ -61,6 +59,7 @@
#endif // BWE_TEST_LOGGING_COMPILE_TIME_ENABLE
namespace webrtc {
+namespace plotting {
namespace {
@@ -128,45 +127,29 @@
return difference;
}
-// This is much more reliable for outgoing streams than for incoming streams.
-template <typename RtpPacketContainer>
-rtc::Optional<uint32_t> EstimateRtpClockFrequency(
- const RtpPacketContainer& packets,
- int64_t end_time_us) {
- RTC_CHECK(packets.size() >= 2);
- SeqNumUnwrapper<uint32_t> unwrapper;
- uint64_t first_rtp_timestamp =
- unwrapper.Unwrap(packets[0].rtp.header.timestamp);
- int64_t first_log_timestamp = packets[0].log_time_us();
- uint64_t last_rtp_timestamp = first_rtp_timestamp;
- int64_t last_log_timestamp = first_log_timestamp;
- for (size_t i = 1; i < packets.size(); i++) {
- if (packets[i].log_time_us() > end_time_us)
- break;
- last_rtp_timestamp = unwrapper.Unwrap(packets[i].rtp.header.timestamp);
- last_log_timestamp = packets[i].log_time_us();
- }
- if (last_log_timestamp - first_log_timestamp < kNumMicrosecsPerSec) {
- RTC_LOG(LS_WARNING)
- << "Failed to estimate RTP clock frequency: Stream too short. ("
- << packets.size() << " packets, "
- << last_log_timestamp - first_log_timestamp << " us)";
- return rtc::nullopt;
- }
- double duration =
- 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}) {
- if (std::fabs(estimated_frequency - f) < 0.05 * f) {
- return f;
- }
- }
- RTC_LOG(LS_WARNING) << "Failed to estimate RTP clock frequency: Estimate "
- << estimated_frequency
- << "not close to any stardard RTP frequency.";
- return rtc::nullopt;
+// Return default values for header extensions, to use on streams without stored
+// mapping data. Currently this only applies to audio streams, since the mapping
+// is not stored in the event log.
+// TODO(ivoc): Remove this once this mapping is stored in the event log for
+// audio streams. Tracking bug: webrtc:6399
+webrtc::RtpHeaderExtensionMap GetDefaultHeaderExtensionMap() {
+ webrtc::RtpHeaderExtensionMap default_map;
+ default_map.Register<AudioLevel>(webrtc::RtpExtension::kAudioLevelDefaultId);
+ default_map.Register<TransmissionOffset>(
+ webrtc::RtpExtension::kTimestampOffsetDefaultId);
+ default_map.Register<AbsoluteSendTime>(
+ webrtc::RtpExtension::kAbsSendTimeDefaultId);
+ default_map.Register<VideoOrientation>(
+ webrtc::RtpExtension::kVideoRotationDefaultId);
+ default_map.Register<VideoContentTypeExtension>(
+ webrtc::RtpExtension::kVideoContentTypeDefaultId);
+ default_map.Register<VideoTimingExtension>(
+ webrtc::RtpExtension::kVideoTimingDefaultId);
+ default_map.Register<TransportSequenceNumber>(
+ webrtc::RtpExtension::kTransportSequenceNumberDefaultId);
+ default_map.Register<PlayoutDelayLimits>(
+ webrtc::RtpExtension::kPlayoutDelayDefaultId);
+ return default_map;
}
constexpr float kLeftMargin = 0.01f;
@@ -182,8 +165,7 @@
int64_t send_time_diff = WrappingDifference(
new_packet.header.extension.absoluteSendTime,
old_packet.header.extension.absoluteSendTime, 1ul << 24);
- int64_t recv_time_diff =
- new_packet.log_time_us() - old_packet.log_time_us();
+ int64_t recv_time_diff = new_packet.timestamp - old_packet.timestamp;
double delay_change_us =
recv_time_diff - AbsSendTimeToMicroseconds(send_time_diff);
return delay_change_us / 1000;
@@ -197,7 +179,7 @@
const LoggedRtpPacket& new_packet) {
int64_t send_time_diff = WrappingDifference(
new_packet.header.timestamp, old_packet.header.timestamp, 1ull << 32);
- int64_t recv_time_diff = new_packet.log_time_us() - old_packet.log_time_us();
+ int64_t recv_time_diff = new_packet.timestamp - old_packet.timestamp;
const double kVideoSampleRate = 90000;
// TODO(terelius): We treat all streams as video for now, even though
@@ -211,9 +193,9 @@
if (delay_change < -10000 || 10000 < delay_change) {
RTC_LOG(LS_WARNING) << "Very large delay change. Timestamps correct?";
RTC_LOG(LS_WARNING) << "Old capture time " << old_packet.header.timestamp
- << ", received time " << old_packet.log_time_us();
+ << ", received time " << old_packet.timestamp;
RTC_LOG(LS_WARNING) << "New capture time " << new_packet.header.timestamp
- << ", received time " << new_packet.log_time_us();
+ << ", received time " << new_packet.timestamp;
RTC_LOG(LS_WARNING) << "Receive time difference " << recv_time_diff << " = "
<< static_cast<double>(recv_time_diff) /
kNumMicrosecsPerSec
@@ -226,55 +208,55 @@
return delay_change;
}
-// For each element in data_view, use |f()| to extract a y-coordinate and
+// For each element in data, use |get_y()| to extract a y-coordinate and
// store the result in a TimeSeries.
-template <typename DataType, typename IterableType>
-void ProcessPoints(rtc::FunctionView<rtc::Optional<float>(const DataType&)> f,
- const IterableType& data_view,
- int64_t begin_time,
- TimeSeries* result) {
- for (size_t i = 0; i < data_view.size(); i++) {
- const DataType& elem = data_view[i];
- float x = static_cast<float>(elem.log_time_us() - begin_time) /
+template <typename DataType>
+void ProcessPoints(
+ rtc::FunctionView<rtc::Optional<float>(const DataType&)> get_y,
+ const std::vector<DataType>& data,
+ 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) /
kNumMicrosecsPerSec;
- rtc::Optional<float> y = f(elem);
+ rtc::Optional<float> y = get_y(data[i]);
if (y)
result->points.emplace_back(x, *y);
}
}
-// For each pair of adjacent elements in |data|, use |f()| to extract a
+// For each pair of adjacent elements in |data|, use |get_y| to extract a
// y-coordinate and store the result in a TimeSeries. Note that the x-coordinate
// will be the time of the second element in the pair.
-template <typename DataType, typename ResultType, typename IterableType>
+template <typename DataType, typename ResultType>
void ProcessPairs(
rtc::FunctionView<rtc::Optional<ResultType>(const DataType&,
- const DataType&)> f,
- const IterableType& data,
- int64_t begin_time,
+ const DataType&)> get_y,
+ const std::vector<DataType>& data,
+ uint64_t begin_time,
TimeSeries* result) {
for (size_t i = 1; i < data.size(); i++) {
- float x = static_cast<float>(data[i].log_time_us() - begin_time) /
+ float x = static_cast<float>(data[i].timestamp - begin_time) /
kNumMicrosecsPerSec;
- rtc::Optional<ResultType> y = f(data[i - 1], data[i]);
+ rtc::Optional<ResultType> y = get_y(data[i - 1], data[i]);
if (y)
result->points.emplace_back(x, static_cast<float>(*y));
}
}
-// For each element in data, use |f()| to extract a y-coordinate and
+// For each element in data, use |extract()| to extract a y-coordinate and
// store the result in a TimeSeries.
-template <typename DataType, typename ResultType, typename IterableType>
+template <typename DataType, typename ResultType>
void AccumulatePoints(
- rtc::FunctionView<rtc::Optional<ResultType>(const DataType&)> f,
- const IterableType& data,
- int64_t begin_time,
+ rtc::FunctionView<rtc::Optional<ResultType>(const DataType&)> extract,
+ const std::vector<DataType>& data,
+ uint64_t begin_time,
TimeSeries* result) {
ResultType sum = 0;
for (size_t i = 0; i < data.size(); i++) {
- float x = static_cast<float>(data[i].log_time_us() - begin_time) /
+ float x = static_cast<float>(data[i].timestamp - begin_time) /
kNumMicrosecsPerSec;
- rtc::Optional<ResultType> y = f(data[i]);
+ rtc::Optional<ResultType> y = extract(data[i]);
if (y) {
sum += *y;
result->points.emplace_back(x, static_cast<float>(sum));
@@ -282,21 +264,21 @@
}
}
-// For each pair of adjacent elements in |data|, use |f()| to extract a
+// For each pair of adjacent elements in |data|, use |extract()| to extract a
// y-coordinate and store the result in a TimeSeries. Note that the x-coordinate
// will be the time of the second element in the pair.
-template <typename DataType, typename ResultType, typename IterableType>
+template <typename DataType, typename ResultType>
void AccumulatePairs(
rtc::FunctionView<rtc::Optional<ResultType>(const DataType&,
- const DataType&)> f,
- const IterableType& data,
- int64_t begin_time,
+ const DataType&)> extract,
+ const std::vector<DataType>& data,
+ uint64_t begin_time,
TimeSeries* result) {
ResultType sum = 0;
for (size_t i = 1; i < data.size(); i++) {
- float x = static_cast<float>(data[i].log_time_us() - begin_time) /
+ float x = static_cast<float>(data[i].timestamp - begin_time) /
kNumMicrosecsPerSec;
- rtc::Optional<ResultType> y = f(data[i - 1], data[i]);
+ rtc::Optional<ResultType> y = extract(data[i - 1], data[i]);
if (y)
sum += *y;
result->points.emplace_back(x, static_cast<float>(sum));
@@ -307,31 +289,30 @@
// A data point is generated every |step| microseconds from |begin_time|
// to |end_time|. The value of each data point is the average of the data
// during the preceeding |window_duration_us| microseconds.
-template <typename DataType, typename ResultType, typename IterableType>
+template <typename DataType, typename ResultType>
void MovingAverage(
- rtc::FunctionView<rtc::Optional<ResultType>(const DataType&)> f,
- const IterableType& data_view,
- int64_t begin_time,
- int64_t end_time,
- int64_t window_duration_us,
- int64_t step,
- TimeSeries* result) {
+ rtc::FunctionView<rtc::Optional<ResultType>(const DataType&)> extract,
+ const std::vector<DataType>& data,
+ uint64_t begin_time,
+ uint64_t end_time,
+ uint64_t window_duration_us,
+ uint64_t step,
+ webrtc::plotting::TimeSeries* result) {
size_t window_index_begin = 0;
size_t window_index_end = 0;
ResultType sum_in_window = 0;
- for (int64_t t = begin_time; t < end_time + step; t += step) {
- while (window_index_end < data_view.size() &&
- data_view[window_index_end].log_time_us() < t) {
- rtc::Optional<ResultType> value = f(data_view[window_index_end]);
+ for (uint64_t t = begin_time; t < end_time + step; t += step) {
+ while (window_index_end < data.size() &&
+ data[window_index_end].timestamp < t) {
+ rtc::Optional<ResultType> value = extract(data[window_index_end]);
if (value)
sum_in_window += *value;
++window_index_end;
}
- while (window_index_begin < data_view.size() &&
- data_view[window_index_begin].log_time_us() <
- t - window_duration_us) {
- rtc::Optional<ResultType> value = f(data_view[window_index_begin]);
+ while (window_index_begin < data.size() &&
+ data[window_index_begin].timestamp < t - window_duration_us) {
+ rtc::Optional<ResultType> value = extract(data[window_index_begin]);
if (value)
sum_in_window -= *value;
++window_index_begin;
@@ -425,7 +406,7 @@
}
std::string GetCandidatePairLogDescriptionAsString(
- const LoggedIceCandidatePairConfig& config) {
+ 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
@@ -448,57 +429,244 @@
return ss.str();
}
-std::string GetDirectionAsString(PacketDirection direction) {
- if (direction == kIncomingPacket) {
- return "Incoming";
- } else {
- return "Outgoing";
- }
-}
-
-std::string GetDirectionAsShortString(PacketDirection direction) {
- if (direction == kIncomingPacket) {
- return "In";
- } else {
- return "Out";
- }
-}
-
} // namespace
EventLogAnalyzer::EventLogAnalyzer(const ParsedRtcEventLog& log)
: parsed_log_(log), window_duration_(250000), step_(10000) {
- begin_time_ = parsed_log_.first_timestamp();
- end_time_ = parsed_log_.last_timestamp();
- if (end_time_ < begin_time_) {
- RTC_LOG(LS_WARNING) << "No useful events in the log.";
- begin_time_ = end_time_ = 0;
- }
- call_duration_s_ = ToCallTime(end_time_);
+ uint64_t first_timestamp = std::numeric_limits<uint64_t>::max();
+ uint64_t last_timestamp = std::numeric_limits<uint64_t>::min();
- const auto& log_start_events = parsed_log_.start_log_events();
- const auto& log_end_events = parsed_log_.stop_log_events();
- auto start_iter = log_start_events.begin();
- auto end_iter = log_end_events.begin();
- while (start_iter != log_start_events.end()) {
- int64_t start = start_iter->log_time_us();
- ++start_iter;
- rtc::Optional<int64_t> next_start;
- if (start_iter != log_start_events.end())
- next_start.emplace(start_iter->log_time_us());
- if (end_iter != log_end_events.end() &&
- end_iter->log_time_us() <=
- next_start.value_or(std::numeric_limits<int64_t>::max())) {
- int64_t end = end_iter->log_time_us();
- RTC_DCHECK_LE(start, end);
- log_segments_.push_back(std::make_pair(start, end));
- ++end_iter;
- } else {
- // we're missing an end event. Assume that it occurred just before the
- // next start.
- log_segments_.push_back(
- std::make_pair(start, next_start.value_or(end_time_)));
+ PacketDirection direction;
+ uint8_t header[IP_PACKET_SIZE];
+ size_t header_length;
+ size_t total_length;
+
+ uint8_t last_incoming_rtcp_packet[IP_PACKET_SIZE];
+ uint8_t last_incoming_rtcp_packet_length = 0;
+
+ // Make a default extension map for streams without configuration information.
+ // TODO(ivoc): Once configuration of audio streams is stored in the event log,
+ // this can be removed. Tracking bug: webrtc:6399
+ RtpHeaderExtensionMap default_extension_map = GetDefaultHeaderExtensionMap();
+
+ rtc::Optional<uint64_t> last_log_start;
+
+ for (size_t i = 0; i < parsed_log_.GetNumberOfEvents(); i++) {
+ ParsedRtcEventLog::EventType event_type = parsed_log_.GetEventType(i);
+ if (event_type != ParsedRtcEventLog::VIDEO_RECEIVER_CONFIG_EVENT &&
+ event_type != ParsedRtcEventLog::VIDEO_SENDER_CONFIG_EVENT &&
+ event_type != ParsedRtcEventLog::AUDIO_RECEIVER_CONFIG_EVENT &&
+ event_type != ParsedRtcEventLog::AUDIO_SENDER_CONFIG_EVENT &&
+ event_type != ParsedRtcEventLog::LOG_START &&
+ event_type != ParsedRtcEventLog::LOG_END) {
+ uint64_t timestamp = parsed_log_.GetTimestamp(i);
+ first_timestamp = std::min(first_timestamp, timestamp);
+ last_timestamp = std::max(last_timestamp, timestamp);
}
+
+ switch (parsed_log_.GetEventType(i)) {
+ case ParsedRtcEventLog::VIDEO_RECEIVER_CONFIG_EVENT: {
+ rtclog::StreamConfig config = parsed_log_.GetVideoReceiveConfig(i);
+ StreamId stream(config.remote_ssrc, kIncomingPacket);
+ video_ssrcs_.insert(stream);
+ StreamId rtx_stream(config.rtx_ssrc, kIncomingPacket);
+ video_ssrcs_.insert(rtx_stream);
+ rtx_ssrcs_.insert(rtx_stream);
+ break;
+ }
+ case ParsedRtcEventLog::VIDEO_SENDER_CONFIG_EVENT: {
+ std::vector<rtclog::StreamConfig> configs =
+ parsed_log_.GetVideoSendConfig(i);
+ for (const auto& config : configs) {
+ StreamId stream(config.local_ssrc, kOutgoingPacket);
+ video_ssrcs_.insert(stream);
+ StreamId rtx_stream(config.rtx_ssrc, kOutgoingPacket);
+ video_ssrcs_.insert(rtx_stream);
+ rtx_ssrcs_.insert(rtx_stream);
+ }
+ break;
+ }
+ case ParsedRtcEventLog::AUDIO_RECEIVER_CONFIG_EVENT: {
+ rtclog::StreamConfig config = parsed_log_.GetAudioReceiveConfig(i);
+ StreamId stream(config.remote_ssrc, kIncomingPacket);
+ audio_ssrcs_.insert(stream);
+ break;
+ }
+ case ParsedRtcEventLog::AUDIO_SENDER_CONFIG_EVENT: {
+ rtclog::StreamConfig config = parsed_log_.GetAudioSendConfig(i);
+ StreamId stream(config.local_ssrc, kOutgoingPacket);
+ audio_ssrcs_.insert(stream);
+ break;
+ }
+ case ParsedRtcEventLog::RTP_EVENT: {
+ RtpHeaderExtensionMap* extension_map = parsed_log_.GetRtpHeader(
+ i, &direction, header, &header_length, &total_length, nullptr);
+ RtpUtility::RtpHeaderParser rtp_parser(header, header_length);
+ RTPHeader parsed_header;
+ if (extension_map != nullptr) {
+ rtp_parser.Parse(&parsed_header, extension_map);
+ } else {
+ // Use the default extension map.
+ // TODO(ivoc): Once configuration of audio streams is stored in the
+ // event log, this can be removed.
+ // Tracking bug: webrtc:6399
+ rtp_parser.Parse(&parsed_header, &default_extension_map);
+ }
+ uint64_t timestamp = parsed_log_.GetTimestamp(i);
+ StreamId stream(parsed_header.ssrc, direction);
+ rtp_packets_[stream].push_back(LoggedRtpPacket(
+ timestamp, parsed_header, header_length, total_length));
+ break;
+ }
+ case ParsedRtcEventLog::RTCP_EVENT: {
+ uint8_t packet[IP_PACKET_SIZE];
+ parsed_log_.GetRtcpPacket(i, &direction, packet, &total_length);
+ // Currently incoming RTCP packets are logged twice, both for audio and
+ // video. Only act on one of them. Compare against the previous parsed
+ // incoming RTCP packet.
+ if (direction == webrtc::kIncomingPacket) {
+ RTC_CHECK_LE(total_length, IP_PACKET_SIZE);
+ if (total_length == last_incoming_rtcp_packet_length &&
+ memcmp(last_incoming_rtcp_packet, packet, total_length) == 0) {
+ continue;
+ } else {
+ memcpy(last_incoming_rtcp_packet, packet, total_length);
+ last_incoming_rtcp_packet_length = total_length;
+ }
+ }
+ rtcp::CommonHeader header;
+ const uint8_t* packet_end = packet + total_length;
+ for (const uint8_t* block = packet; block < packet_end;
+ block = header.NextPacket()) {
+ RTC_CHECK(header.Parse(block, packet_end - block));
+ if (header.type() == rtcp::TransportFeedback::kPacketType &&
+ header.fmt() == rtcp::TransportFeedback::kFeedbackMessageType) {
+ std::unique_ptr<rtcp::TransportFeedback> rtcp_packet(
+ rtc::MakeUnique<rtcp::TransportFeedback>());
+ if (rtcp_packet->Parse(header)) {
+ uint32_t ssrc = rtcp_packet->sender_ssrc();
+ StreamId stream(ssrc, direction);
+ uint64_t timestamp = parsed_log_.GetTimestamp(i);
+ rtcp_packets_[stream].push_back(LoggedRtcpPacket(
+ timestamp, kRtcpTransportFeedback, std::move(rtcp_packet)));
+ }
+ } else if (header.type() == rtcp::SenderReport::kPacketType) {
+ std::unique_ptr<rtcp::SenderReport> rtcp_packet(
+ rtc::MakeUnique<rtcp::SenderReport>());
+ if (rtcp_packet->Parse(header)) {
+ uint32_t ssrc = rtcp_packet->sender_ssrc();
+ StreamId stream(ssrc, direction);
+ uint64_t timestamp = parsed_log_.GetTimestamp(i);
+ rtcp_packets_[stream].push_back(
+ LoggedRtcpPacket(timestamp, kRtcpSr, std::move(rtcp_packet)));
+ }
+ } else if (header.type() == rtcp::ReceiverReport::kPacketType) {
+ std::unique_ptr<rtcp::ReceiverReport> rtcp_packet(
+ rtc::MakeUnique<rtcp::ReceiverReport>());
+ if (rtcp_packet->Parse(header)) {
+ uint32_t ssrc = rtcp_packet->sender_ssrc();
+ StreamId stream(ssrc, direction);
+ uint64_t timestamp = parsed_log_.GetTimestamp(i);
+ rtcp_packets_[stream].push_back(
+ LoggedRtcpPacket(timestamp, kRtcpRr, std::move(rtcp_packet)));
+ }
+ } else if (header.type() == rtcp::Remb::kPacketType &&
+ header.fmt() == rtcp::Remb::kFeedbackMessageType) {
+ std::unique_ptr<rtcp::Remb> rtcp_packet(
+ rtc::MakeUnique<rtcp::Remb>());
+ if (rtcp_packet->Parse(header)) {
+ uint32_t ssrc = rtcp_packet->sender_ssrc();
+ StreamId stream(ssrc, direction);
+ uint64_t timestamp = parsed_log_.GetTimestamp(i);
+ rtcp_packets_[stream].push_back(LoggedRtcpPacket(
+ timestamp, kRtcpRemb, std::move(rtcp_packet)));
+ }
+ }
+ }
+ break;
+ }
+ case ParsedRtcEventLog::LOG_START: {
+ if (last_log_start) {
+ // A LOG_END event was missing. Use last_timestamp.
+ RTC_DCHECK_GE(last_timestamp, *last_log_start);
+ log_segments_.push_back(
+ std::make_pair(*last_log_start, last_timestamp));
+ }
+ last_log_start = parsed_log_.GetTimestamp(i);
+ break;
+ }
+ case ParsedRtcEventLog::LOG_END: {
+ RTC_DCHECK(last_log_start);
+ log_segments_.push_back(
+ std::make_pair(*last_log_start, parsed_log_.GetTimestamp(i)));
+ last_log_start.reset();
+ break;
+ }
+ case ParsedRtcEventLog::AUDIO_PLAYOUT_EVENT: {
+ uint32_t this_ssrc;
+ parsed_log_.GetAudioPlayout(i, &this_ssrc);
+ audio_playout_events_[this_ssrc].push_back(parsed_log_.GetTimestamp(i));
+ break;
+ }
+ case ParsedRtcEventLog::LOSS_BASED_BWE_UPDATE: {
+ LossBasedBweUpdate bwe_update;
+ bwe_update.timestamp = parsed_log_.GetTimestamp(i);
+ parsed_log_.GetLossBasedBweUpdate(i, &bwe_update.new_bitrate,
+ &bwe_update.fraction_loss,
+ &bwe_update.expected_packets);
+ bwe_loss_updates_.push_back(bwe_update);
+ break;
+ }
+ case ParsedRtcEventLog::DELAY_BASED_BWE_UPDATE: {
+ bwe_delay_updates_.push_back(parsed_log_.GetDelayBasedBweUpdate(i));
+ break;
+ }
+ case ParsedRtcEventLog::AUDIO_NETWORK_ADAPTATION_EVENT: {
+ AudioNetworkAdaptationEvent ana_event;
+ ana_event.timestamp = parsed_log_.GetTimestamp(i);
+ parsed_log_.GetAudioNetworkAdaptation(i, &ana_event.config);
+ audio_network_adaptation_events_.push_back(ana_event);
+ break;
+ }
+ case ParsedRtcEventLog::BWE_PROBE_CLUSTER_CREATED_EVENT: {
+ bwe_probe_cluster_created_events_.push_back(
+ parsed_log_.GetBweProbeClusterCreated(i));
+ break;
+ }
+ case ParsedRtcEventLog::BWE_PROBE_RESULT_EVENT: {
+ bwe_probe_result_events_.push_back(parsed_log_.GetBweProbeResult(i));
+ break;
+ }
+ case ParsedRtcEventLog::ALR_STATE_EVENT: {
+ 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;
+ }
+ }
+ }
+
+ if (last_timestamp < first_timestamp) {
+ // No useful events in the log.
+ first_timestamp = last_timestamp = 0;
+ }
+ begin_time_ = first_timestamp;
+ end_time_ = last_timestamp;
+ 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_));
}
RTC_LOG(LS_INFO) << "Found " << log_segments_.size()
<< " (LOG_START, LOG_END) segments in log.";
@@ -510,7 +678,7 @@
BitrateObserver() : last_bitrate_bps_(0), bitrate_updated_(false) {}
void OnNetworkChanged(uint32_t bitrate_bps,
- uint8_t fraction_lost,
+ uint8_t fraction_loss,
int64_t rtt_ms,
int64_t probing_interval_ms) override {
last_bitrate_bps_ = bitrate_bps;
@@ -532,90 +700,187 @@
bool bitrate_updated_;
};
+bool EventLogAnalyzer::IsRtxSsrc(StreamId stream_id) const {
+ return rtx_ssrcs_.count(stream_id) == 1;
+}
+
+bool EventLogAnalyzer::IsVideoSsrc(StreamId stream_id) const {
+ return video_ssrcs_.count(stream_id) == 1;
+}
+
+bool EventLogAnalyzer::IsAudioSsrc(StreamId stream_id) const {
+ return audio_ssrcs_.count(stream_id) == 1;
+}
+
+std::string EventLogAnalyzer::GetStreamName(StreamId stream_id) const {
+ std::stringstream name;
+ if (IsAudioSsrc(stream_id)) {
+ name << "Audio ";
+ } else if (IsVideoSsrc(stream_id)) {
+ name << "Video ";
+ } else {
+ name << "Unknown ";
+ }
+ if (IsRtxSsrc(stream_id))
+ name << "RTX ";
+ if (stream_id.GetDirection() == kIncomingPacket) {
+ name << "(In) ";
+ } else {
+ name << "(Out) ";
+ }
+ name << SsrcToString(stream_id.GetSsrc());
+ return name.str();
+}
+
+// This is much more reliable for outgoing streams than for incoming streams.
+rtc::Optional<uint32_t> EventLogAnalyzer::EstimateRtpClockFrequency(
+ const std::vector<LoggedRtpPacket>& packets) const {
+ RTC_CHECK(packets.size() >= 2);
+ uint64_t end_time_us = log_segments_.empty()
+ ? std::numeric_limits<uint64_t>::max()
+ : log_segments_.front().second;
+ SeqNumUnwrapper<uint32_t> unwrapper;
+ uint64_t first_rtp_timestamp = unwrapper.Unwrap(packets[0].header.timestamp);
+ uint64_t first_log_timestamp = packets[0].timestamp;
+ uint64_t last_rtp_timestamp = first_rtp_timestamp;
+ uint64_t last_log_timestamp = first_log_timestamp;
+ for (size_t i = 1; i < packets.size(); i++) {
+ if (packets[i].timestamp > end_time_us)
+ break;
+ last_rtp_timestamp = unwrapper.Unwrap(packets[i].header.timestamp);
+ last_log_timestamp = packets[i].timestamp;
+ }
+ if (last_log_timestamp - first_log_timestamp < kNumMicrosecsPerSec) {
+ RTC_LOG(LS_WARNING)
+ << "Failed to estimate RTP clock frequency: Stream too short. ("
+ << packets.size() << " packets, "
+ << last_log_timestamp - first_log_timestamp << " us)";
+ return rtc::nullopt;
+ }
+ double duration =
+ 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}) {
+ if (std::fabs(estimated_frequency - f) < 0.05 * f) {
+ return f;
+ }
+ }
+ RTC_LOG(LS_WARNING) << "Failed to estimate RTP clock frequency: Estimate "
+ << estimated_frequency
+ << "not close to any stardard RTP frequency.";
+ return rtc::nullopt;
+}
+
float EventLogAnalyzer::ToCallTime(int64_t timestamp) const {
return static_cast<float>(timestamp - begin_time_) / kNumMicrosecsPerSec;
}
-void EventLogAnalyzer::CreatePacketGraph(PacketDirection direction,
+void EventLogAnalyzer::CreatePacketGraph(PacketDirection desired_direction,
Plot* plot) {
- for (const auto& stream : parsed_log_.rtp_packets_by_ssrc(direction)) {
- // Filter on SSRC.
- if (!MatchingSsrc(stream.ssrc, desired_ssrc_)) {
+ for (auto& kv : rtp_packets_) {
+ StreamId stream_id = kv.first;
+ const std::vector<LoggedRtpPacket>& packet_stream = kv.second;
+ // Filter on direction and SSRC.
+ if (stream_id.GetDirection() != desired_direction ||
+ !MatchingSsrc(stream_id.GetSsrc(), desired_ssrc_)) {
continue;
}
- TimeSeries time_series(GetStreamName(direction, stream.ssrc),
- LineStyle::kBar);
- auto GetPacketSize = [](const LoggedRtpPacket& packet) {
- return rtc::Optional<float>(packet.total_length);
- };
- ProcessPoints<LoggedRtpPacket>(GetPacketSize, stream.packet_view,
- begin_time_, &time_series);
+ TimeSeries time_series(GetStreamName(stream_id), LineStyle::kBar);
+ ProcessPoints<LoggedRtpPacket>(
+ [](const LoggedRtpPacket& packet) {
+ return rtc::Optional<float>(packet.total_length);
+ },
+ packet_stream, begin_time_, &time_series);
plot->AppendTimeSeries(std::move(time_series));
}
plot->SetXAxis(0, call_duration_s_, "Time (s)", kLeftMargin, kRightMargin);
plot->SetSuggestedYAxis(0, 1, "Packet size (bytes)", kBottomMargin,
kTopMargin);
- plot->SetTitle(GetDirectionAsString(direction) + " RTP packets");
+ if (desired_direction == webrtc::PacketDirection::kIncomingPacket) {
+ plot->SetTitle("Incoming RTP packets");
+ } else if (desired_direction == webrtc::PacketDirection::kOutgoingPacket) {
+ plot->SetTitle("Outgoing RTP packets");
+ }
}
-template <typename IterableType>
+template <typename T>
void EventLogAnalyzer::CreateAccumulatedPacketsTimeSeries(
+ PacketDirection desired_direction,
Plot* plot,
- const IterableType& packets,
- const std::string& label) {
- TimeSeries time_series(label, LineStyle::kStep);
- for (size_t i = 0; i < packets.size(); i++) {
- float x = ToCallTime(packets[i].log_time_us());
- time_series.points.emplace_back(x, i + 1);
+ const std::map<StreamId, std::vector<T>>& packets,
+ const std::string& label_prefix) {
+ for (auto& kv : packets) {
+ StreamId stream_id = kv.first;
+ const std::vector<T>& packet_stream = kv.second;
+ // Filter on direction and SSRC.
+ if (stream_id.GetDirection() != desired_direction ||
+ !MatchingSsrc(stream_id.GetSsrc(), desired_ssrc_)) {
+ continue;
+ }
+
+ 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 = ToCallTime(packet_stream[i].timestamp);
+ time_series.points.emplace_back(x, i + 1);
+ }
+
+ plot->AppendTimeSeries(std::move(time_series));
}
- plot->AppendTimeSeries(std::move(time_series));
}
-void EventLogAnalyzer::CreateAccumulatedPacketsGraph(PacketDirection direction,
- Plot* plot) {
- for (const auto& stream : parsed_log_.rtp_packets_by_ssrc(direction)) {
- if (!MatchingSsrc(stream.ssrc, desired_ssrc_))
- continue;
- std::string label =
- std::string("RTP ") + GetStreamName(direction, stream.ssrc);
- CreateAccumulatedPacketsTimeSeries(plot, stream.packet_view, label);
- }
- std::string label =
- std::string("RTCP ") + "(" + GetDirectionAsShortString(direction) + ")";
- if (direction == kIncomingPacket) {
- CreateAccumulatedPacketsTimeSeries(
- plot, parsed_log_.incoming_rtcp_packets(), label);
- } else {
- CreateAccumulatedPacketsTimeSeries(
- plot, parsed_log_.outgoing_rtcp_packets(), label);
- }
+void EventLogAnalyzer::CreateAccumulatedPacketsGraph(
+ PacketDirection desired_direction,
+ Plot* plot) {
+ CreateAccumulatedPacketsTimeSeries(desired_direction, plot, rtp_packets_,
+ "RTP");
+ CreateAccumulatedPacketsTimeSeries(desired_direction, plot, rtcp_packets_,
+ "RTCP");
plot->SetXAxis(0, call_duration_s_, "Time (s)", kLeftMargin, kRightMargin);
plot->SetSuggestedYAxis(0, 1, "Received Packets", kBottomMargin, kTopMargin);
- plot->SetTitle(std::string("Accumulated ") + GetDirectionAsString(direction) +
- " RTP/RTCP packets");
+ if (desired_direction == webrtc::PacketDirection::kIncomingPacket) {
+ plot->SetTitle("Accumulated Incoming RTP/RTCP packets");
+ } else if (desired_direction == webrtc::PacketDirection::kOutgoingPacket) {
+ plot->SetTitle("Accumulated Outgoing RTP/RTCP packets");
+ }
}
// For each SSRC, plot the time between the consecutive playouts.
void EventLogAnalyzer::CreatePlayoutGraph(Plot* plot) {
- for (const auto& playout_stream : parsed_log_.audio_playout_events()) {
- uint32_t ssrc = playout_stream.first;
- if (!MatchingSsrc(ssrc, desired_ssrc_))
- continue;
- rtc::Optional<int64_t> last_playout;
- TimeSeries time_series(SsrcToString(ssrc), LineStyle::kBar);
- for (const auto& playout_time : playout_stream.second) {
- float x = ToCallTime(playout_time);
- // If there were no previous playouts, place the point on the x-axis.
- float y = static_cast<float>(playout_time -
- last_playout.value_or(playout_time)) /
- 1000;
- time_series.points.push_back(TimeSeriesPoint(x, y));
- last_playout.emplace(playout_time);
+ std::map<uint32_t, TimeSeries> time_series;
+ std::map<uint32_t, uint64_t> last_playout;
+
+ uint32_t ssrc;
+
+ for (size_t i = 0; i < parsed_log_.GetNumberOfEvents(); i++) {
+ ParsedRtcEventLog::EventType event_type = parsed_log_.GetEventType(i);
+ if (event_type == ParsedRtcEventLog::AUDIO_PLAYOUT_EVENT) {
+ parsed_log_.GetAudioPlayout(i, &ssrc);
+ uint64_t timestamp = parsed_log_.GetTimestamp(i);
+ if (MatchingSsrc(ssrc, desired_ssrc_)) {
+ 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.
+ // Generate a point, but place it on the x-axis.
+ y = 0;
+ }
+ time_series[ssrc].points.push_back(TimeSeriesPoint(x, y));
+ last_playout[ssrc] = timestamp;
+ }
}
- plot->AppendTimeSeries(std::move(time_series));
+ }
+
+ // Set labels and put in graph.
+ for (auto& kv : time_series) {
+ kv.second.label = SsrcToString(kv.first);
+ kv.second.line_style = LineStyle::kBar;
+ plot->AppendTimeSeries(std::move(kv.second));
}
plot->SetXAxis(0, call_duration_s_, "Time (s)", kLeftMargin, kRightMargin);
@@ -625,51 +890,59 @@
}
// For audio SSRCs, plot the audio level.
-void EventLogAnalyzer::CreateAudioLevelGraph(PacketDirection direction,
- Plot* plot) {
- for (const auto& stream : parsed_log_.rtp_packets_by_ssrc(direction)) {
- if (!IsAudioSsrc(direction, stream.ssrc))
- continue;
- TimeSeries time_series(GetStreamName(direction, stream.ssrc),
- LineStyle::kLine);
- for (auto& packet : stream.packet_view) {
+void EventLogAnalyzer::CreateAudioLevelGraph(Plot* plot) {
+ std::map<StreamId, TimeSeries> time_series;
+
+ for (auto& kv : rtp_packets_) {
+ StreamId stream_id = kv.first;
+ const std::vector<LoggedRtpPacket>& packet_stream = kv.second;
+ // TODO(ivoc): When audio send/receive configs are stored in the event
+ // log, a check should be added here to only process audio
+ // streams. Tracking bug: webrtc:6399
+ for (auto& packet : packet_stream) {
if (packet.header.extension.hasAudioLevel) {
- float x = ToCallTime(packet.log_time_us());
+ 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);
- time_series.points.emplace_back(TimeSeriesPoint(x, y));
+ time_series[stream_id].points.emplace_back(TimeSeriesPoint(x, y));
}
}
- plot->AppendTimeSeries(std::move(time_series));
+ }
+
+ for (auto& series : time_series) {
+ series.second.label = GetStreamName(series.first);
+ series.second.line_style = LineStyle::kLine;
+ plot->AppendTimeSeries(std::move(series.second));
}
plot->SetXAxis(0, call_duration_s_, "Time (s)", kLeftMargin, kRightMargin);
plot->SetYAxis(-127, 0, "Audio level (dBov)", kBottomMargin,
kTopMargin);
- plot->SetTitle(GetDirectionAsString(direction) + " audio level");
+ plot->SetTitle("Audio level");
}
// For each SSRC, plot the time between the consecutive playouts.
void EventLogAnalyzer::CreateSequenceNumberGraph(Plot* plot) {
- for (const auto& stream : parsed_log_.incoming_rtp_packets_by_ssrc()) {
- // Filter on SSRC.
- if (!MatchingSsrc(stream.ssrc, desired_ssrc_)) {
+ for (auto& kv : rtp_packets_) {
+ StreamId stream_id = kv.first;
+ const std::vector<LoggedRtpPacket>& packet_stream = kv.second;
+ // Filter on direction and SSRC.
+ if (stream_id.GetDirection() != kIncomingPacket ||
+ !MatchingSsrc(stream_id.GetSsrc(), desired_ssrc_)) {
continue;
}
- TimeSeries time_series(GetStreamName(kIncomingPacket, stream.ssrc),
- LineStyle::kBar);
- auto GetSequenceNumberDiff = [](const LoggedRtpPacketIncoming& old_packet,
- const LoggedRtpPacketIncoming& new_packet) {
- int64_t diff =
- WrappingDifference(new_packet.rtp.header.sequenceNumber,
- old_packet.rtp.header.sequenceNumber, 1ul << 16);
- return diff;
- };
- ProcessPairs<LoggedRtpPacketIncoming, float>(GetSequenceNumberDiff,
- stream.incoming_packets,
- begin_time_, &time_series);
+ TimeSeries time_series(GetStreamName(stream_id), LineStyle::kBar);
+ ProcessPairs<LoggedRtpPacket, float>(
+ [](const LoggedRtpPacket& old_packet,
+ const LoggedRtpPacket& new_packet) {
+ int64_t diff =
+ WrappingDifference(new_packet.header.sequenceNumber,
+ old_packet.header.sequenceNumber, 1ul << 16);
+ return diff;
+ },
+ packet_stream, begin_time_, &time_series);
plot->AppendTimeSeries(std::move(time_series));
}
@@ -680,47 +953,47 @@
}
void EventLogAnalyzer::CreateIncomingPacketLossGraph(Plot* plot) {
- for (const auto& stream : parsed_log_.incoming_rtp_packets_by_ssrc()) {
- const std::vector<LoggedRtpPacketIncoming>& packets =
- stream.incoming_packets;
- // Filter on SSRC.
- if (!MatchingSsrc(stream.ssrc, desired_ssrc_) || packets.size() == 0) {
+ for (auto& kv : rtp_packets_) {
+ StreamId stream_id = kv.first;
+ const std::vector<LoggedRtpPacket>& packet_stream = kv.second;
+ // Filter on direction and SSRC.
+ if (stream_id.GetDirection() != kIncomingPacket ||
+ !MatchingSsrc(stream_id.GetSsrc(), desired_ssrc_) ||
+ packet_stream.size() == 0) {
continue;
}
- TimeSeries time_series(GetStreamName(kIncomingPacket, stream.ssrc),
- LineStyle::kLine, PointStyle::kHighlight);
- // TODO(terelius): Should the window and step size be read from the class
- // instead?
- const int64_t kWindowUs = 1000000;
- const int64_t kStep = 1000000;
+ TimeSeries time_series(GetStreamName(stream_id), LineStyle::kLine,
+ PointStyle::kHighlight);
+ const uint64_t kWindowUs = 1000000;
+ const uint64_t kStep = 1000000;
SeqNumUnwrapper<uint16_t> unwrapper_;
SeqNumUnwrapper<uint16_t> prior_unwrapper_;
size_t window_index_begin = 0;
size_t window_index_end = 0;
- uint64_t highest_seq_number =
- unwrapper_.Unwrap(packets[0].rtp.header.sequenceNumber) - 1;
- uint64_t highest_prior_seq_number =
- prior_unwrapper_.Unwrap(packets[0].rtp.header.sequenceNumber) - 1;
+ int64_t highest_seq_number =
+ unwrapper_.Unwrap(packet_stream[0].header.sequenceNumber) - 1;
+ int64_t highest_prior_seq_number =
+ prior_unwrapper_.Unwrap(packet_stream[0].header.sequenceNumber) - 1;
- for (int64_t t = begin_time_; t < end_time_ + kStep; t += kStep) {
- while (window_index_end < packets.size() &&
- packets[window_index_end].rtp.log_time_us() < t) {
- uint64_t sequence_number = unwrapper_.Unwrap(
- packets[window_index_end].rtp.header.sequenceNumber);
+ for (uint64_t t = begin_time_; t < end_time_ + kStep; t += kStep) {
+ while (window_index_end < packet_stream.size() &&
+ packet_stream[window_index_end].timestamp < t) {
+ int64_t sequence_number = unwrapper_.Unwrap(
+ packet_stream[window_index_end].header.sequenceNumber);
highest_seq_number = std::max(highest_seq_number, sequence_number);
++window_index_end;
}
- while (window_index_begin < packets.size() &&
- packets[window_index_begin].rtp.log_time_us() < t - kWindowUs) {
- uint64_t sequence_number = prior_unwrapper_.Unwrap(
- packets[window_index_begin].rtp.header.sequenceNumber);
+ while (window_index_begin < packet_stream.size() &&
+ packet_stream[window_index_begin].timestamp < t - kWindowUs) {
+ int64_t sequence_number = prior_unwrapper_.Unwrap(
+ packet_stream[window_index_begin].header.sequenceNumber);
highest_prior_seq_number =
std::max(highest_prior_seq_number, sequence_number);
++window_index_begin;
}
float x = ToCallTime(t);
- uint64_t expected_packets = highest_seq_number - highest_prior_seq_number;
+ 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;
int64_t lost_packets = expected_packets - received_packets;
@@ -738,28 +1011,28 @@
}
void EventLogAnalyzer::CreateIncomingDelayDeltaGraph(Plot* plot) {
- for (const auto& stream : parsed_log_.rtp_packets_by_ssrc(kIncomingPacket)) {
- // Filter on SSRC.
- if (!MatchingSsrc(stream.ssrc, desired_ssrc_) ||
- IsAudioSsrc(kIncomingPacket, stream.ssrc) ||
- !IsVideoSsrc(kIncomingPacket, stream.ssrc) ||
- IsRtxSsrc(kIncomingPacket, stream.ssrc)) {
+ for (auto& kv : rtp_packets_) {
+ StreamId stream_id = kv.first;
+ const std::vector<LoggedRtpPacket>& packet_stream = kv.second;
+ // Filter on direction and SSRC.
+ if (stream_id.GetDirection() != kIncomingPacket ||
+ !MatchingSsrc(stream_id.GetSsrc(), desired_ssrc_) ||
+ IsAudioSsrc(stream_id) || !IsVideoSsrc(stream_id) ||
+ IsRtxSsrc(stream_id)) {
continue;
}
- TimeSeries capture_time_data(
- GetStreamName(kIncomingPacket, stream.ssrc) + " capture-time",
- LineStyle::kBar);
+ TimeSeries capture_time_data(GetStreamName(stream_id) + " capture-time",
+ LineStyle::kBar);
ProcessPairs<LoggedRtpPacket, double>(NetworkDelayDiff_CaptureTime,
- stream.packet_view, begin_time_,
+ packet_stream, begin_time_,
&capture_time_data);
plot->AppendTimeSeries(std::move(capture_time_data));
- TimeSeries send_time_data(
- GetStreamName(kIncomingPacket, stream.ssrc) + " abs-send-time",
- LineStyle::kBar);
+ TimeSeries send_time_data(GetStreamName(stream_id) + " abs-send-time",
+ LineStyle::kBar);
ProcessPairs<LoggedRtpPacket, double>(NetworkDelayDiff_AbsSendTime,
- stream.packet_view, begin_time_,
+ packet_stream, begin_time_,
&send_time_data);
plot->AppendTimeSeries(std::move(send_time_data));
}
@@ -771,28 +1044,28 @@
}
void EventLogAnalyzer::CreateIncomingDelayGraph(Plot* plot) {
- for (const auto& stream : parsed_log_.rtp_packets_by_ssrc(kIncomingPacket)) {
- // Filter on SSRC.
- if (!MatchingSsrc(stream.ssrc, desired_ssrc_) ||
- IsAudioSsrc(kIncomingPacket, stream.ssrc) ||
- !IsVideoSsrc(kIncomingPacket, stream.ssrc) ||
- IsRtxSsrc(kIncomingPacket, stream.ssrc)) {
+ for (auto& kv : rtp_packets_) {
+ StreamId stream_id = kv.first;
+ const std::vector<LoggedRtpPacket>& packet_stream = kv.second;
+ // Filter on direction and SSRC.
+ if (stream_id.GetDirection() != kIncomingPacket ||
+ !MatchingSsrc(stream_id.GetSsrc(), desired_ssrc_) ||
+ IsAudioSsrc(stream_id) || !IsVideoSsrc(stream_id) ||
+ IsRtxSsrc(stream_id)) {
continue;
}
- TimeSeries capture_time_data(
- GetStreamName(kIncomingPacket, stream.ssrc) + " capture-time",
- LineStyle::kLine);
+ TimeSeries capture_time_data(GetStreamName(stream_id) + " capture-time",
+ LineStyle::kLine);
AccumulatePairs<LoggedRtpPacket, double>(NetworkDelayDiff_CaptureTime,
- stream.packet_view, begin_time_,
+ packet_stream, begin_time_,
&capture_time_data);
plot->AppendTimeSeries(std::move(capture_time_data));
- TimeSeries send_time_data(
- GetStreamName(kIncomingPacket, stream.ssrc) + " abs-send-time",
- LineStyle::kLine);
+ TimeSeries send_time_data(GetStreamName(stream_id) + " abs-send-time",
+ LineStyle::kLine);
AccumulatePairs<LoggedRtpPacket, double>(NetworkDelayDiff_AbsSendTime,
- stream.packet_view, begin_time_,
+ packet_stream, begin_time_,
&send_time_data);
plot->AppendTimeSeries(std::move(send_time_data));
}
@@ -807,9 +1080,9 @@
void EventLogAnalyzer::CreateFractionLossGraph(Plot* plot) {
TimeSeries time_series("Fraction lost", LineStyle::kLine,
PointStyle::kHighlight);
- for (auto& bwe_update : parsed_log_.bwe_loss_updates()) {
- float x = ToCallTime(bwe_update.log_time_us());
- float y = static_cast<float>(bwe_update.fraction_lost) / 255 * 100;
+ for (auto& bwe_update : bwe_loss_updates_) {
+ float x = ToCallTime(bwe_update.timestamp);
+ float y = static_cast<float>(bwe_update.fraction_loss) / 255 * 100;
time_series.points.emplace_back(x, y);
}
@@ -821,82 +1094,51 @@
}
// Plot the total bandwidth used by all RTP streams.
-void EventLogAnalyzer::CreateTotalIncomingBitrateGraph(Plot* plot) {
- // TODO(terelius): This could be provided by the parser.
- std::multimap<int64_t, size_t> packets_in_order;
- for (const auto& stream : parsed_log_.incoming_rtp_packets_by_ssrc()) {
- for (const LoggedRtpPacketIncoming& packet : stream.incoming_packets)
- packets_in_order.insert(
- std::make_pair(packet.rtp.log_time_us(), packet.rtp.total_length));
+void EventLogAnalyzer::CreateTotalBitrateGraph(
+ PacketDirection desired_direction,
+ Plot* plot,
+ bool show_detector_state,
+ bool show_alr_state) {
+ struct TimestampSize {
+ TimestampSize(uint64_t t, size_t s) : timestamp(t), size(s) {}
+ uint64_t timestamp;
+ size_t size;
+ };
+ std::vector<TimestampSize> packets;
+
+ PacketDirection direction;
+ size_t total_length;
+
+ // Extract timestamps and sizes for the relevant packets.
+ for (size_t i = 0; i < parsed_log_.GetNumberOfEvents(); i++) {
+ ParsedRtcEventLog::EventType event_type = parsed_log_.GetEventType(i);
+ if (event_type == ParsedRtcEventLog::RTP_EVENT) {
+ parsed_log_.GetRtpHeader(i, &direction, nullptr, nullptr, &total_length,
+ nullptr);
+ if (direction == desired_direction) {
+ uint64_t timestamp = parsed_log_.GetTimestamp(i);
+ packets.push_back(TimestampSize(timestamp, total_length));
+ }
+ }
}
- auto window_begin = packets_in_order.begin();
- auto window_end = packets_in_order.begin();
+ size_t window_index_begin = 0;
+ size_t window_index_end = 0;
size_t bytes_in_window = 0;
// Calculate a moving average of the bitrate and store in a TimeSeries.
TimeSeries bitrate_series("Bitrate", LineStyle::kLine);
- for (int64_t time = begin_time_; time < end_time_ + step_; time += step_) {
- while (window_end != packets_in_order.end() && window_end->first < time) {
- bytes_in_window += window_end->second;
- ++window_end;
+ for (uint64_t time = begin_time_; time < end_time_ + step_; time += step_) {
+ while (window_index_end < packets.size() &&
+ packets[window_index_end].timestamp < time) {
+ bytes_in_window += packets[window_index_end].size;
+ ++window_index_end;
}
- while (window_begin != packets_in_order.end() &&
- window_begin->first < time - window_duration_) {
- RTC_DCHECK_LE(window_begin->second, bytes_in_window);
- bytes_in_window -= window_begin->second;
- ++window_begin;
- }
- float window_duration_in_seconds =
- 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);
- }
- plot->AppendTimeSeries(std::move(bitrate_series));
-
- // Overlay the outgoing REMB over incoming bitrate.
- TimeSeries remb_series("Remb", LineStyle::kStep);
- for (const auto& rtcp : parsed_log_.rembs(kOutgoingPacket)) {
- float x = ToCallTime(rtcp.log_time_us());
- float y = static_cast<float>(rtcp.remb.bitrate_bps()) / 1000;
- remb_series.points.emplace_back(x, y);
- }
- plot->AppendTimeSeriesIfNotEmpty(std::move(remb_series));
-
- plot->SetXAxis(0, call_duration_s_, "Time (s)", kLeftMargin, kRightMargin);
- plot->SetSuggestedYAxis(0, 1, "Bitrate (kbps)", kBottomMargin, kTopMargin);
- plot->SetTitle("Incoming RTP bitrate");
-}
-
-// Plot the total bandwidth used by all RTP streams.
-void EventLogAnalyzer::CreateTotalOutgoingBitrateGraph(Plot* plot,
- bool show_detector_state,
- bool show_alr_state) {
- // TODO(terelius): This could be provided by the parser.
- std::multimap<int64_t, size_t> packets_in_order;
- for (const auto& stream : parsed_log_.outgoing_rtp_packets_by_ssrc()) {
- for (const LoggedRtpPacketOutgoing& packet : stream.outgoing_packets)
- packets_in_order.insert(
- std::make_pair(packet.rtp.log_time_us(), packet.rtp.total_length));
- }
-
- auto window_begin = packets_in_order.begin();
- auto window_end = packets_in_order.begin();
- size_t bytes_in_window = 0;
-
- // Calculate a moving average of the bitrate and store in a TimeSeries.
- TimeSeries bitrate_series("Bitrate", LineStyle::kLine);
- for (int64_t time = begin_time_; time < end_time_ + step_; time += step_) {
- while (window_end != packets_in_order.end() && window_end->first < time) {
- bytes_in_window += window_end->second;
- ++window_end;
- }
- while (window_begin != packets_in_order.end() &&
- window_begin->first < time - window_duration_) {
- RTC_DCHECK_LE(window_begin->second, bytes_in_window);
- bytes_in_window -= window_begin->second;
- ++window_begin;
+ while (window_index_begin < packets.size() &&
+ packets[window_index_begin].timestamp < time - window_duration_) {
+ RTC_DCHECK_LE(packets[window_index_begin].size, bytes_in_window);
+ bytes_in_window -= packets[window_index_begin].size;
+ ++window_index_begin;
}
float window_duration_in_seconds =
static_cast<float>(window_duration_) / kNumMicrosecsPerSec;
@@ -907,161 +1149,195 @@
plot->AppendTimeSeries(std::move(bitrate_series));
// Overlay the send-side bandwidth estimate over the outgoing bitrate.
- TimeSeries loss_series("Loss-based estimate", LineStyle::kStep);
- for (auto& loss_update : parsed_log_.bwe_loss_updates()) {
- float x = ToCallTime(loss_update.log_time_us());
- float y = static_cast<float>(loss_update.bitrate_bps) / 1000;
- loss_series.points.emplace_back(x, y);
- }
+ if (desired_direction == kOutgoingPacket) {
+ TimeSeries loss_series("Loss-based estimate", LineStyle::kStep);
+ for (auto& loss_update : bwe_loss_updates_) {
+ float x = ToCallTime(loss_update.timestamp);
+ float y = static_cast<float>(loss_update.new_bitrate) / 1000;
+ loss_series.points.emplace_back(x, y);
+ }
- TimeSeries delay_series("Delay-based estimate", LineStyle::kStep);
- IntervalSeries overusing_series("Overusing", "#ff8e82",
- IntervalSeries::kHorizontal);
- IntervalSeries underusing_series("Underusing", "#5092fc",
- IntervalSeries::kHorizontal);
- IntervalSeries normal_series("Normal", "#c4ffc4",
- IntervalSeries::kHorizontal);
- IntervalSeries* last_series = &normal_series;
- double last_detector_switch = 0.0;
+ TimeSeries delay_series("Delay-based estimate", LineStyle::kStep);
+ IntervalSeries overusing_series("Overusing", "#ff8e82",
+ IntervalSeries::kHorizontal);
+ IntervalSeries underusing_series("Underusing", "#5092fc",
+ IntervalSeries::kHorizontal);
+ IntervalSeries normal_series("Normal", "#c4ffc4",
+ IntervalSeries::kHorizontal);
+ IntervalSeries* last_series = &normal_series;
+ double last_detector_switch = 0.0;
- BandwidthUsage last_detector_state = BandwidthUsage::kBwNormal;
+ BandwidthUsage last_detector_state = BandwidthUsage::kBwNormal;
- for (auto& delay_update : parsed_log_.bwe_delay_updates()) {
- float x = ToCallTime(delay_update.log_time_us());
- float y = static_cast<float>(delay_update.bitrate_bps) / 1000;
+ for (auto& delay_update : bwe_delay_updates_) {
+ float x = ToCallTime(delay_update.timestamp);
+ float y = static_cast<float>(delay_update.bitrate_bps) / 1000;
- if (last_detector_state != delay_update.detector_state) {
- last_series->intervals.emplace_back(last_detector_switch, x);
- last_detector_state = delay_update.detector_state;
- last_detector_switch = x;
+ if (last_detector_state != delay_update.detector_state) {
+ last_series->intervals.emplace_back(last_detector_switch, x);
+ last_detector_state = delay_update.detector_state;
+ last_detector_switch = x;
- switch (delay_update.detector_state) {
- case BandwidthUsage::kBwNormal:
- last_series = &normal_series;
- break;
- case BandwidthUsage::kBwUnderusing:
- last_series = &underusing_series;
- break;
- case BandwidthUsage::kBwOverusing:
- last_series = &overusing_series;
- break;
- case BandwidthUsage::kLast:
- RTC_NOTREACHED();
+ switch (delay_update.detector_state) {
+ case BandwidthUsage::kBwNormal:
+ last_series = &normal_series;
+ break;
+ case BandwidthUsage::kBwUnderusing:
+ last_series = &underusing_series;
+ break;
+ case BandwidthUsage::kBwOverusing:
+ last_series = &overusing_series;
+ break;
+ case BandwidthUsage::kLast:
+ RTC_NOTREACHED();
+ }
+ }
+
+ delay_series.points.emplace_back(x, y);
+ }
+
+ RTC_CHECK(last_series);
+ last_series->intervals.emplace_back(last_detector_switch, end_time_);
+
+ TimeSeries created_series("Probe cluster created.", LineStyle::kNone,
+ PointStyle::kHighlight);
+ for (auto& cluster : bwe_probe_cluster_created_events_) {
+ float x = ToCallTime(cluster.timestamp);
+ float y = static_cast<float>(cluster.bitrate_bps) / 1000;
+ created_series.points.emplace_back(x, y);
+ }
+
+ TimeSeries result_series("Probing results.", LineStyle::kNone,
+ PointStyle::kHighlight);
+ for (auto& result : bwe_probe_result_events_) {
+ if (result.bitrate_bps) {
+ float x = ToCallTime(result.timestamp);
+ float y = static_cast<float>(*result.bitrate_bps) / 1000;
+ result_series.points.emplace_back(x, y);
}
}
- delay_series.points.emplace_back(x, y);
- }
-
- RTC_CHECK(last_series);
- last_series->intervals.emplace_back(last_detector_switch, end_time_);
-
- TimeSeries created_series("Probe cluster created.", LineStyle::kNone,
- PointStyle::kHighlight);
- for (auto& cluster : parsed_log_.bwe_probe_cluster_created_events()) {
- float x = ToCallTime(cluster.log_time_us());
- float y = static_cast<float>(cluster.bitrate_bps) / 1000;
- created_series.points.emplace_back(x, y);
- }
-
- TimeSeries result_series("Probing results.", LineStyle::kNone,
- PointStyle::kHighlight);
- for (auto& result : parsed_log_.bwe_probe_result_events()) {
- if (result.bitrate_bps) {
- float x = ToCallTime(result.log_time_us());
- float y = static_cast<float>(*result.bitrate_bps) / 1000;
- result_series.points.emplace_back(x, y);
+ IntervalSeries alr_state("ALR", "#555555", IntervalSeries::kHorizontal);
+ bool previously_in_alr = false;
+ int64_t alr_start = 0;
+ for (auto& alr : alr_state_events_) {
+ float y = ToCallTime(alr.timestamp);
+ if (!previously_in_alr && alr.in_alr) {
+ alr_start = alr.timestamp;
+ previously_in_alr = true;
+ } else if (previously_in_alr && !alr.in_alr) {
+ float x = ToCallTime(alr_start);
+ alr_state.intervals.emplace_back(x, y);
+ previously_in_alr = false;
+ }
}
- }
- IntervalSeries alr_state("ALR", "#555555", IntervalSeries::kHorizontal);
- bool previously_in_alr = false;
- int64_t alr_start = 0;
- for (auto& alr : parsed_log_.alr_state_events()) {
- float y = ToCallTime(alr.log_time_us());
- if (!previously_in_alr && alr.in_alr) {
- alr_start = alr.log_time_us();
- previously_in_alr = true;
- } else if (previously_in_alr && !alr.in_alr) {
+ if (previously_in_alr) {
float x = ToCallTime(alr_start);
+ float y = ToCallTime(end_time_);
alr_state.intervals.emplace_back(x, y);
- previously_in_alr = false;
+ }
+
+ if (show_detector_state) {
+ plot->AppendIntervalSeries(std::move(overusing_series));
+ plot->AppendIntervalSeries(std::move(underusing_series));
+ plot->AppendIntervalSeries(std::move(normal_series));
+ }
+
+ if (show_alr_state) {
+ plot->AppendIntervalSeries(std::move(alr_state));
+ }
+ plot->AppendTimeSeries(std::move(loss_series));
+ plot->AppendTimeSeries(std::move(delay_series));
+ plot->AppendTimeSeries(std::move(created_series));
+ plot->AppendTimeSeries(std::move(result_series));
+ }
+
+ // Overlay the incoming REMB over the outgoing bitrate
+ // and outgoing REMB over incoming bitrate.
+ PacketDirection remb_direction =
+ desired_direction == kOutgoingPacket ? kIncomingPacket : kOutgoingPacket;
+ TimeSeries remb_series("Remb", LineStyle::kStep);
+ std::multimap<uint64_t, const LoggedRtcpPacket*> remb_packets;
+ for (const auto& kv : rtcp_packets_) {
+ if (kv.first.GetDirection() == remb_direction) {
+ for (const LoggedRtcpPacket& rtcp_packet : kv.second) {
+ if (rtcp_packet.type == kRtcpRemb) {
+ remb_packets.insert(
+ std::make_pair(rtcp_packet.timestamp, &rtcp_packet));
+ }
+ }
}
}
- if (previously_in_alr) {
- float x = ToCallTime(alr_start);
- float y = ToCallTime(end_time_);
- alr_state.intervals.emplace_back(x, y);
- }
-
- if (show_detector_state) {
- plot->AppendIntervalSeries(std::move(overusing_series));
- plot->AppendIntervalSeries(std::move(underusing_series));
- plot->AppendIntervalSeries(std::move(normal_series));
- }
-
- if (show_alr_state) {
- plot->AppendIntervalSeries(std::move(alr_state));
- }
- plot->AppendTimeSeries(std::move(loss_series));
- plot->AppendTimeSeries(std::move(delay_series));
- plot->AppendTimeSeries(std::move(created_series));
- plot->AppendTimeSeries(std::move(result_series));
-
- // Overlay the incoming REMB over the outgoing bitrate.
- TimeSeries remb_series("Remb", LineStyle::kStep);
- for (const auto& rtcp : parsed_log_.rembs(kIncomingPacket)) {
- float x = ToCallTime(rtcp.log_time_us());
- float y = static_cast<float>(rtcp.remb.bitrate_bps()) / 1000;
+ 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 = ToCallTime(rtcp->timestamp);
+ float y = static_cast<float>(remb->bitrate_bps()) / 1000;
remb_series.points.emplace_back(x, y);
}
plot->AppendTimeSeriesIfNotEmpty(std::move(remb_series));
plot->SetXAxis(0, call_duration_s_, "Time (s)", kLeftMargin, kRightMargin);
plot->SetSuggestedYAxis(0, 1, "Bitrate (kbps)", kBottomMargin, kTopMargin);
- plot->SetTitle("Outgoing RTP bitrate");
+ if (desired_direction == webrtc::PacketDirection::kIncomingPacket) {
+ plot->SetTitle("Incoming RTP bitrate");
+ } else if (desired_direction == webrtc::PacketDirection::kOutgoingPacket) {
+ plot->SetTitle("Outgoing RTP bitrate");
+ }
}
// For each SSRC, plot the bandwidth used by that stream.
-void EventLogAnalyzer::CreateStreamBitrateGraph(PacketDirection direction,
- Plot* plot) {
- for (const auto& stream : parsed_log_.rtp_packets_by_ssrc(direction)) {
- // Filter on SSRC.
- if (!MatchingSsrc(stream.ssrc, desired_ssrc_)) {
+void EventLogAnalyzer::CreateStreamBitrateGraph(
+ PacketDirection desired_direction,
+ Plot* plot) {
+ for (auto& kv : rtp_packets_) {
+ StreamId stream_id = kv.first;
+ const std::vector<LoggedRtpPacket>& packet_stream = kv.second;
+ // Filter on direction and SSRC.
+ if (stream_id.GetDirection() != desired_direction ||
+ !MatchingSsrc(stream_id.GetSsrc(), desired_ssrc_)) {
continue;
}
- TimeSeries time_series(GetStreamName(direction, stream.ssrc),
- LineStyle::kLine);
- auto GetPacketSizeKilobits = [](const LoggedRtpPacket& packet) {
- return packet.total_length * 8.0 / 1000.0;
- };
+ TimeSeries time_series(GetStreamName(stream_id), LineStyle::kLine);
MovingAverage<LoggedRtpPacket, double>(
- GetPacketSizeKilobits, stream.packet_view, begin_time_, end_time_,
- window_duration_, step_, &time_series);
+ [](const LoggedRtpPacket& packet) {
+ return packet.total_length * 8.0 / 1000.0;
+ },
+ packet_stream, begin_time_, end_time_, window_duration_, step_,
+ &time_series);
plot->AppendTimeSeries(std::move(time_series));
}
plot->SetXAxis(0, call_duration_s_, "Time (s)", kLeftMargin, kRightMargin);
plot->SetSuggestedYAxis(0, 1, "Bitrate (kbps)", kBottomMargin, kTopMargin);
- plot->SetTitle(GetDirectionAsString(direction) + " bitrate per stream");
+ if (desired_direction == webrtc::PacketDirection::kIncomingPacket) {
+ plot->SetTitle("Incoming bitrate per stream");
+ } else if (desired_direction == webrtc::PacketDirection::kOutgoingPacket) {
+ plot->SetTitle("Outgoing bitrate per stream");
+ }
}
void EventLogAnalyzer::CreateSendSideBweSimulationGraph(Plot* plot) {
- using RtpPacketType = LoggedRtpPacketOutgoing;
- using TransportFeedbackType = LoggedRtcpPacketTransportFeedback;
+ std::multimap<uint64_t, const LoggedRtpPacket*> outgoing_rtp;
+ std::multimap<uint64_t, const LoggedRtcpPacket*> incoming_rtcp;
- // TODO(terelius): This could be provided by the parser.
- std::multimap<int64_t, const RtpPacketType*> outgoing_rtp;
- for (const auto& stream : parsed_log_.outgoing_rtp_packets_by_ssrc()) {
- for (const RtpPacketType& rtp_packet : stream.outgoing_packets)
- outgoing_rtp.insert(
- std::make_pair(rtp_packet.rtp.log_time_us(), &rtp_packet));
+ for (const auto& kv : rtp_packets_) {
+ if (kv.first.GetDirection() == PacketDirection::kOutgoingPacket) {
+ for (const LoggedRtpPacket& rtp_packet : kv.second)
+ outgoing_rtp.insert(std::make_pair(rtp_packet.timestamp, &rtp_packet));
+ }
}
- const std::vector<TransportFeedbackType>& incoming_rtcp =
- parsed_log_.transport_feedbacks(kIncomingPacket);
+ for (const auto& kv : rtcp_packets_) {
+ if (kv.first.GetDirection() == PacketDirection::kIncomingPacket) {
+ for (const LoggedRtcpPacket& rtcp_packet : kv.second)
+ incoming_rtcp.insert(
+ std::make_pair(rtcp_packet.timestamp, &rtcp_packet));
+ }
+ }
SimulatedClock clock(0);
BitrateObserver observer;
@@ -1091,7 +1367,7 @@
auto NextRtcpTime = [&]() {
if (rtcp_iterator != incoming_rtcp.end())
- return static_cast<int64_t>(rtcp_iterator->log_time_us());
+ return static_cast<int64_t>(rtcp_iterator->first);
return std::numeric_limits<int64_t>::max();
};
@@ -1122,38 +1398,41 @@
clock.AdvanceTimeMicroseconds(time_us - clock.TimeInMicroseconds());
if (clock.TimeInMicroseconds() >= NextRtcpTime()) {
RTC_DCHECK_EQ(clock.TimeInMicroseconds(), NextRtcpTime());
- cc.OnTransportFeedback(rtcp_iterator->transport_feedback);
- std::vector<PacketFeedback> feedback = cc.GetTransportFeedbackVector();
- SortPacketFeedbackVector(&feedback);
- rtc::Optional<uint32_t> bitrate_bps;
- if (!feedback.empty()) {
+ const LoggedRtcpPacket& rtcp = *rtcp_iterator->second;
+ if (rtcp.type == kRtcpTransportFeedback) {
+ cc.OnTransportFeedback(
+ *static_cast<rtcp::TransportFeedback*>(rtcp.packet.get()));
+ std::vector<PacketFeedback> feedback = cc.GetTransportFeedbackVector();
+ SortPacketFeedbackVector(&feedback);
+ rtc::Optional<uint32_t> bitrate_bps;
+ if (!feedback.empty()) {
#if !(BWE_TEST_LOGGING_COMPILE_TIME_ENABLE)
- acknowledged_bitrate_estimator.IncomingPacketFeedbackVector(feedback);
+ acknowledged_bitrate_estimator.IncomingPacketFeedbackVector(feedback);
#endif // !(BWE_TEST_LOGGING_COMPILE_TIME_ENABLE)
- for (const PacketFeedback& packet : feedback)
- acked_bitrate.Update(packet.payload_size, packet.arrival_time_ms);
- bitrate_bps = acked_bitrate.Rate(feedback.back().arrival_time_ms);
+ for (const PacketFeedback& packet : feedback)
+ acked_bitrate.Update(packet.payload_size, packet.arrival_time_ms);
+ bitrate_bps = acked_bitrate.Rate(feedback.back().arrival_time_ms);
+ }
+ 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)
+ y = acknowledged_bitrate_estimator.bitrate_bps().value_or(0) / 1000;
+ acked_estimate_time_series.points.emplace_back(x, y);
+#endif // !(BWE_TEST_LOGGING_COMPILE_TIME_ENABLE)
}
- 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)
- y = acknowledged_bitrate_estimator.bitrate_bps().value_or(0) / 1000;
- acked_estimate_time_series.points.emplace_back(x, y);
-#endif // !(BWE_TEST_LOGGING_COMPILE_TIME_ENABLE)
++rtcp_iterator;
}
if (clock.TimeInMicroseconds() >= NextRtpTime()) {
RTC_DCHECK_EQ(clock.TimeInMicroseconds(), NextRtpTime());
- const RtpPacketType& rtp_packet = *rtp_iterator->second;
- if (rtp_packet.rtp.header.extension.hasTransportSequenceNumber) {
- RTC_DCHECK(rtp_packet.rtp.header.extension.hasTransportSequenceNumber);
- cc.AddPacket(rtp_packet.rtp.header.ssrc,
- rtp_packet.rtp.header.extension.transportSequenceNumber,
- rtp_packet.rtp.total_length, PacedPacketInfo());
+ const LoggedRtpPacket& rtp = *rtp_iterator->second;
+ if (rtp.header.extension.hasTransportSequenceNumber) {
+ RTC_DCHECK(rtp.header.extension.hasTransportSequenceNumber);
+ cc.AddPacket(rtp.header.ssrc,
+ rtp.header.extension.transportSequenceNumber,
+ rtp.total_length, PacedPacketInfo());
rtc::SentPacket sent_packet(
- rtp_packet.rtp.header.extension.transportSequenceNumber,
- rtp_packet.rtp.log_time_us() / 1000);
+ rtp.header.extension.transportSequenceNumber, rtp.timestamp / 1000);
cc.OnSentPacket(sent_packet);
}
++rtp_iterator;
@@ -1182,7 +1461,6 @@
}
void EventLogAnalyzer::CreateReceiveSideBweSimulationGraph(Plot* plot) {
- using RtpPacketType = LoggedRtpPacketIncoming;
class RembInterceptingPacketRouter : public PacketRouter {
public:
void OnReceiveBitrateChanged(const std::vector<uint32_t>& ssrcs,
@@ -1203,19 +1481,19 @@
bool bitrate_updated_;
};
- std::multimap<int64_t, const RtpPacketType*> incoming_rtp;
+ std::multimap<uint64_t, const LoggedRtpPacket*> incoming_rtp;
- for (const auto& stream : parsed_log_.incoming_rtp_packets_by_ssrc()) {
- if (IsVideoSsrc(kIncomingPacket, stream.ssrc)) {
- for (const auto& rtp_packet : stream.incoming_packets)
- incoming_rtp.insert(
- std::make_pair(rtp_packet.rtp.log_time_us(), &rtp_packet));
+ for (const auto& kv : rtp_packets_) {
+ if (kv.first.GetDirection() == PacketDirection::kIncomingPacket &&
+ IsVideoSsrc(kv.first)) {
+ for (const LoggedRtpPacket& rtp_packet : kv.second)
+ incoming_rtp.insert(std::make_pair(rtp_packet.timestamp, &rtp_packet));
}
}
SimulatedClock clock(0);
RembInterceptingPacketRouter packet_router;
- // TODO(terelius): The PacketRouter is used as the RemoteBitrateObserver.
+ // TODO(terelius): The PacketRrouter is the used as the RemoteBitrateObserver.
// Is this intentional?
ReceiveSideCongestionController rscc(&clock, &packet_router);
// TODO(holmer): Log the call config and use that here instead.
@@ -1229,12 +1507,12 @@
RateStatistics acked_bitrate(250, 8000);
int64_t last_update_us = 0;
for (const auto& kv : incoming_rtp) {
- const RtpPacketType& packet = *kv.second;
- int64_t arrival_time_ms = packet.rtp.log_time_us() / 1000;
- size_t payload = packet.rtp.total_length; /*Should subtract header?*/
- clock.AdvanceTimeMicroseconds(packet.rtp.log_time_us() -
+ const LoggedRtpPacket& packet = *kv.second;
+ int64_t arrival_time_ms = packet.timestamp / 1000;
+ size_t payload = packet.total_length; /*Should subtract header?*/
+ clock.AdvanceTimeMicroseconds(packet.timestamp -
clock.TimeInMicroseconds());
- rscc.OnReceivedPacket(arrival_time_ms, payload, packet.rtp.header);
+ rscc.OnReceivedPacket(arrival_time_ms, payload, packet.header);
acked_bitrate.Update(payload, arrival_time_ms);
rtc::Optional<uint32_t> bitrate_bps = acked_bitrate.Rate(arrival_time_ms);
if (bitrate_bps) {
@@ -1260,19 +1538,23 @@
}
void EventLogAnalyzer::CreateNetworkDelayFeedbackGraph(Plot* plot) {
- using RtpPacketType = LoggedRtpPacketOutgoing;
- using TransportFeedbackType = LoggedRtcpPacketTransportFeedback;
+ std::multimap<uint64_t, const LoggedRtpPacket*> outgoing_rtp;
+ std::multimap<uint64_t, const LoggedRtcpPacket*> incoming_rtcp;
- // TODO(terelius): This could be provided by the parser.
- std::multimap<int64_t, const RtpPacketType*> outgoing_rtp;
- for (const auto& stream : parsed_log_.outgoing_rtp_packets_by_ssrc()) {
- for (const RtpPacketType& rtp_packet : stream.outgoing_packets)
- outgoing_rtp.insert(
- std::make_pair(rtp_packet.rtp.log_time_us(), &rtp_packet));
+ for (const auto& kv : rtp_packets_) {
+ if (kv.first.GetDirection() == PacketDirection::kOutgoingPacket) {
+ for (const LoggedRtpPacket& rtp_packet : kv.second)
+ outgoing_rtp.insert(std::make_pair(rtp_packet.timestamp, &rtp_packet));
+ }
}
- const std::vector<TransportFeedbackType>& incoming_rtcp =
- parsed_log_.transport_feedbacks(kIncomingPacket);
+ for (const auto& kv : rtcp_packets_) {
+ if (kv.first.GetDirection() == PacketDirection::kIncomingPacket) {
+ for (const LoggedRtcpPacket& rtcp_packet : kv.second)
+ incoming_rtcp.insert(
+ std::make_pair(rtcp_packet.timestamp, &rtcp_packet));
+ }
+ }
SimulatedClock clock(0);
TransportFeedbackAdapter feedback_adapter(&clock);
@@ -1294,7 +1576,7 @@
auto NextRtcpTime = [&]() {
if (rtcp_iterator != incoming_rtcp.end())
- return static_cast<int64_t>(rtcp_iterator->log_time_us());
+ return static_cast<int64_t>(rtcp_iterator->first);
return std::numeric_limits<int64_t>::max();
};
@@ -1304,34 +1586,37 @@
clock.AdvanceTimeMicroseconds(time_us - clock.TimeInMicroseconds());
if (clock.TimeInMicroseconds() >= NextRtcpTime()) {
RTC_DCHECK_EQ(clock.TimeInMicroseconds(), NextRtcpTime());
- feedback_adapter.OnTransportFeedback(rtcp_iterator->transport_feedback);
- std::vector<PacketFeedback> feedback =
- feedback_adapter.GetTransportFeedbackVector();
- SortPacketFeedbackVector(&feedback);
- for (const PacketFeedback& packet : feedback) {
- float x = ToCallTime(clock.TimeInMicroseconds());
- if (packet.send_time_ms == PacketFeedback::kNoSendTime) {
- late_feedback_series.points.emplace_back(x, prev_y);
- continue;
+ const LoggedRtcpPacket& rtcp = *rtcp_iterator->second;
+ if (rtcp.type == kRtcpTransportFeedback) {
+ feedback_adapter.OnTransportFeedback(
+ *static_cast<rtcp::TransportFeedback*>(rtcp.packet.get()));
+ std::vector<PacketFeedback> feedback =
+ feedback_adapter.GetTransportFeedbackVector();
+ SortPacketFeedbackVector(&feedback);
+ for (const PacketFeedback& packet : feedback) {
+ float x = ToCallTime(clock.TimeInMicroseconds());
+ if (packet.send_time_ms == PacketFeedback::kNoSendTime) {
+ late_feedback_series.points.emplace_back(x, prev_y);
+ continue;
+ }
+ int64_t y = packet.arrival_time_ms - packet.send_time_ms;
+ prev_y = y;
+ estimated_base_delay_ms = std::min(y, estimated_base_delay_ms);
+ time_series.points.emplace_back(x, y);
}
- int64_t y = packet.arrival_time_ms - packet.send_time_ms;
- prev_y = y;
- estimated_base_delay_ms = std::min(y, estimated_base_delay_ms);
- time_series.points.emplace_back(x, y);
}
++rtcp_iterator;
}
if (clock.TimeInMicroseconds() >= NextRtpTime()) {
RTC_DCHECK_EQ(clock.TimeInMicroseconds(), NextRtpTime());
- const RtpPacketType& rtp_packet = *rtp_iterator->second;
- if (rtp_packet.rtp.header.extension.hasTransportSequenceNumber) {
- feedback_adapter.AddPacket(
- rtp_packet.rtp.header.ssrc,
- rtp_packet.rtp.header.extension.transportSequenceNumber,
- rtp_packet.rtp.total_length, PacedPacketInfo());
+ const LoggedRtpPacket& rtp = *rtp_iterator->second;
+ if (rtp.header.extension.hasTransportSequenceNumber) {
+ RTC_DCHECK(rtp.header.extension.hasTransportSequenceNumber);
+ feedback_adapter.AddPacket(rtp.header.ssrc,
+ rtp.header.extension.transportSequenceNumber,
+ rtp.total_length, PacedPacketInfo());
feedback_adapter.OnSentPacket(
- rtp_packet.rtp.header.extension.transportSequenceNumber,
- rtp_packet.rtp.log_time_us() / 1000);
+ rtp.header.extension.transportSequenceNumber, rtp.timestamp / 1000);
}
++rtp_iterator;
}
@@ -1352,10 +1637,40 @@
plot->SetTitle("Network Delay Change.");
}
+std::vector<std::pair<int64_t, int64_t>> EventLogAnalyzer::GetFrameTimestamps()
+ const {
+ std::vector<std::pair<int64_t, int64_t>> timestamps;
+ size_t largest_stream_size = 0;
+ const std::vector<LoggedRtpPacket>* largest_video_stream = nullptr;
+ // Find the incoming video stream with the most number of packets that is
+ // not rtx.
+ for (const auto& kv : rtp_packets_) {
+ if (kv.first.GetDirection() == kIncomingPacket &&
+ video_ssrcs_.find(kv.first) != video_ssrcs_.end() &&
+ rtx_ssrcs_.find(kv.first) == rtx_ssrcs_.end() &&
+ kv.second.size() > largest_stream_size) {
+ largest_stream_size = kv.second.size();
+ largest_video_stream = &kv.second;
+ }
+ }
+ if (largest_video_stream == nullptr) {
+ for (auto& packet : *largest_video_stream) {
+ if (packet.header.markerBit) {
+ int64_t capture_ms = packet.header.timestamp / 90.0;
+ int64_t arrival_ms = packet.timestamp / 1000.0;
+ timestamps.push_back(std::make_pair(capture_ms, arrival_ms));
+ }
+ }
+ }
+ return timestamps;
+}
+
void EventLogAnalyzer::CreatePacerDelayGraph(Plot* plot) {
- for (const auto& stream : parsed_log_.outgoing_rtp_packets_by_ssrc()) {
- const std::vector<LoggedRtpPacketOutgoing>& packets =
- stream.outgoing_packets;
+ for (const auto& kv : rtp_packets_) {
+ const std::vector<LoggedRtpPacket>& packets = kv.second;
+ StreamId stream_id = kv.first;
+ if (stream_id.GetDirection() == kIncomingPacket)
+ continue;
if (packets.size() < 2) {
RTC_LOG(LS_WARNING)
@@ -1363,15 +1678,11 @@
"pacer delay with less than 2 packets in the stream";
continue;
}
- int64_t end_time_us = log_segments_.empty()
- ? std::numeric_limits<int64_t>::max()
- : log_segments_.front().second;
rtc::Optional<uint32_t> estimated_frequency =
- EstimateRtpClockFrequency(packets, end_time_us);
+ EstimateRtpClockFrequency(packets);
if (!estimated_frequency)
continue;
- if (IsVideoSsrc(kOutgoingPacket, stream.ssrc) &&
- *estimated_frequency != 90000) {
+ if (IsVideoSsrc(stream_id) && *estimated_frequency != 90000) {
RTC_LOG(LS_WARNING)
<< "Video stream should use a 90 kHz clock but appears to use "
<< *estimated_frequency / 1000 << ". Discarding.";
@@ -1379,22 +1690,21 @@
}
TimeSeries pacer_delay_series(
- GetStreamName(kOutgoingPacket, stream.ssrc) + "(" +
+ GetStreamName(stream_id) + "(" +
std::to_string(*estimated_frequency / 1000) + " kHz)",
LineStyle::kLine, PointStyle::kHighlight);
SeqNumUnwrapper<uint32_t> timestamp_unwrapper;
uint64_t first_capture_timestamp =
- timestamp_unwrapper.Unwrap(packets.front().rtp.header.timestamp);
- uint64_t first_send_timestamp = packets.front().rtp.log_time_us();
- for (const auto& packet : packets) {
+ timestamp_unwrapper.Unwrap(packets.front().header.timestamp);
+ uint64_t first_send_timestamp = packets.front().timestamp;
+ for (LoggedRtpPacket packet : packets) {
double capture_time_ms = (static_cast<double>(timestamp_unwrapper.Unwrap(
- packet.rtp.header.timestamp)) -
+ packet.header.timestamp)) -
first_capture_timestamp) /
*estimated_frequency * 1000;
double send_time_ms =
- static_cast<double>(packet.rtp.log_time_us() - first_send_timestamp) /
- 1000;
- float x = ToCallTime(packet.rtp.log_time_us());
+ static_cast<double>(packet.timestamp - first_send_timestamp) / 1000;
+ float x = ToCallTime(packet.timestamp);
float y = send_time_ms - capture_time_ms;
pacer_delay_series.points.emplace_back(x, y);
}
@@ -1407,52 +1717,58 @@
"Delay from capture to send time. (First packet normalized to 0.)");
}
-void EventLogAnalyzer::CreateTimestampGraph(PacketDirection direction,
- Plot* plot) {
- for (const auto& stream : parsed_log_.rtp_packets_by_ssrc(direction)) {
- TimeSeries rtp_timestamps(
- GetStreamName(direction, stream.ssrc) + " capture-time",
- LineStyle::kLine, PointStyle::kHighlight);
- for (const auto& packet : stream.packet_view) {
- float x = ToCallTime(packet.log_time_us());
- float y = packet.header.timestamp;
- rtp_timestamps.points.emplace_back(x, y);
- }
- plot->AppendTimeSeries(std::move(rtp_timestamps));
+void EventLogAnalyzer::CreateTimestampGraph(Plot* plot) {
+ for (const auto& kv : rtp_packets_) {
+ const std::vector<LoggedRtpPacket>& rtp_packets = kv.second;
+ StreamId stream_id = kv.first;
- TimeSeries rtcp_timestamps(
- GetStreamName(direction, stream.ssrc) + " rtcp capture-time",
- LineStyle::kLine, PointStyle::kHighlight);
- // TODO(terelius): Why only sender reports?
- const auto& sender_reports = parsed_log_.sender_reports(direction);
- for (const auto& rtcp : sender_reports) {
- if (rtcp.sr.sender_ssrc() != stream.ssrc)
- continue;
- float x = ToCallTime(rtcp.log_time_us());
- float y = rtcp.sr.rtp_timestamp();
- rtcp_timestamps.points.emplace_back(x, y);
+ {
+ TimeSeries timestamp_data(GetStreamName(stream_id) + " capture-time",
+ LineStyle::kLine, PointStyle::kHighlight);
+ for (LoggedRtpPacket packet : rtp_packets) {
+ float x = ToCallTime(packet.timestamp);
+ float y = packet.header.timestamp;
+ timestamp_data.points.emplace_back(x, y);
+ }
+ plot->AppendTimeSeries(std::move(timestamp_data));
}
- plot->AppendTimeSeriesIfNotEmpty(std::move(rtcp_timestamps));
+
+ {
+ auto kv = rtcp_packets_.find(stream_id);
+ if (kv != rtcp_packets_.end()) {
+ const auto& packets = kv->second;
+ TimeSeries timestamp_data(
+ GetStreamName(stream_id) + " rtcp capture-time", LineStyle::kLine,
+ PointStyle::kHighlight);
+ for (const LoggedRtcpPacket& rtcp : packets) {
+ if (rtcp.type != kRtcpSr)
+ continue;
+ rtcp::SenderReport* sr;
+ sr = static_cast<rtcp::SenderReport*>(rtcp.packet.get());
+ float x = ToCallTime(rtcp.timestamp);
+ float y = sr->rtp_timestamp();
+ timestamp_data.points.emplace_back(x, y);
+ }
+ plot->AppendTimeSeries(std::move(timestamp_data));
+ }
+ }
}
plot->SetXAxis(0, call_duration_s_, "Time (s)", kLeftMargin, kRightMargin);
- plot->SetSuggestedYAxis(0, 1, "RTP timestamp", kBottomMargin, kTopMargin);
- plot->SetTitle(GetDirectionAsString(direction) + " timestamps");
+ plot->SetSuggestedYAxis(0, 1, "Timestamp (90khz)", kBottomMargin, kTopMargin);
+ plot->SetTitle("Timestamps");
}
void EventLogAnalyzer::CreateAudioEncoderTargetBitrateGraph(Plot* plot) {
TimeSeries time_series("Audio encoder target bitrate", LineStyle::kLine,
PointStyle::kHighlight);
- auto GetAnaBitrateBps = [](const LoggedAudioNetworkAdaptationEvent& ana_event)
- -> rtc::Optional<float> {
- if (ana_event.config.bitrate_bps)
- return rtc::Optional<float>(
- static_cast<float>(*ana_event.config.bitrate_bps));
- return rtc::nullopt;
- };
- ProcessPoints<LoggedAudioNetworkAdaptationEvent>(
- GetAnaBitrateBps, parsed_log_.audio_network_adaptation_events(),
- begin_time_, &time_series);
+ ProcessPoints<AudioNetworkAdaptationEvent>(
+ [](const AudioNetworkAdaptationEvent& ana_event) -> rtc::Optional<float> {
+ if (ana_event.config.bitrate_bps)
+ return static_cast<float>(*ana_event.config.bitrate_bps);
+ return rtc::nullopt;
+ },
+ audio_network_adaptation_events_, begin_time_, &time_series);
plot->AppendTimeSeries(std::move(time_series));
plot->SetXAxis(0, call_duration_s_, "Time (s)", kLeftMargin, kRightMargin);
plot->SetSuggestedYAxis(0, 1, "Bitrate (bps)", kBottomMargin, kTopMargin);
@@ -1462,16 +1778,14 @@
void EventLogAnalyzer::CreateAudioEncoderFrameLengthGraph(Plot* plot) {
TimeSeries time_series("Audio encoder frame length", LineStyle::kLine,
PointStyle::kHighlight);
- auto GetAnaFrameLengthMs =
- [](const LoggedAudioNetworkAdaptationEvent& ana_event) {
+ ProcessPoints<AudioNetworkAdaptationEvent>(
+ [](const AudioNetworkAdaptationEvent& ana_event) {
if (ana_event.config.frame_length_ms)
return rtc::Optional<float>(
static_cast<float>(*ana_event.config.frame_length_ms));
return rtc::Optional<float>();
- };
- ProcessPoints<LoggedAudioNetworkAdaptationEvent>(
- GetAnaFrameLengthMs, parsed_log_.audio_network_adaptation_events(),
- begin_time_, &time_series);
+ },
+ audio_network_adaptation_events_, begin_time_, &time_series);
plot->AppendTimeSeries(std::move(time_series));
plot->SetXAxis(0, call_duration_s_, "Time (s)", kLeftMargin, kRightMargin);
plot->SetSuggestedYAxis(0, 1, "Frame length (ms)", kBottomMargin, kTopMargin);
@@ -1481,16 +1795,14 @@
void EventLogAnalyzer::CreateAudioEncoderPacketLossGraph(Plot* plot) {
TimeSeries time_series("Audio encoder uplink packet loss fraction",
LineStyle::kLine, PointStyle::kHighlight);
- auto GetAnaPacketLoss =
- [](const LoggedAudioNetworkAdaptationEvent& ana_event) {
+ ProcessPoints<AudioNetworkAdaptationEvent>(
+ [](const AudioNetworkAdaptationEvent& ana_event) {
if (ana_event.config.uplink_packet_loss_fraction)
return rtc::Optional<float>(static_cast<float>(
*ana_event.config.uplink_packet_loss_fraction));
return rtc::Optional<float>();
- };
- ProcessPoints<LoggedAudioNetworkAdaptationEvent>(
- GetAnaPacketLoss, parsed_log_.audio_network_adaptation_events(),
- begin_time_, &time_series);
+ },
+ audio_network_adaptation_events_, begin_time_, &time_series);
plot->AppendTimeSeries(std::move(time_series));
plot->SetXAxis(0, call_duration_s_, "Time (s)", kLeftMargin, kRightMargin);
plot->SetSuggestedYAxis(0, 10, "Percent lost packets", kBottomMargin,
@@ -1501,16 +1813,14 @@
void EventLogAnalyzer::CreateAudioEncoderEnableFecGraph(Plot* plot) {
TimeSeries time_series("Audio encoder FEC", LineStyle::kLine,
PointStyle::kHighlight);
- auto GetAnaFecEnabled =
- [](const LoggedAudioNetworkAdaptationEvent& ana_event) {
+ ProcessPoints<AudioNetworkAdaptationEvent>(
+ [](const AudioNetworkAdaptationEvent& ana_event) {
if (ana_event.config.enable_fec)
return rtc::Optional<float>(
static_cast<float>(*ana_event.config.enable_fec));
return rtc::Optional<float>();
- };
- ProcessPoints<LoggedAudioNetworkAdaptationEvent>(
- GetAnaFecEnabled, parsed_log_.audio_network_adaptation_events(),
- begin_time_, &time_series);
+ },
+ audio_network_adaptation_events_, begin_time_, &time_series);
plot->AppendTimeSeries(std::move(time_series));
plot->SetXAxis(0, call_duration_s_, "Time (s)", kLeftMargin, kRightMargin);
plot->SetSuggestedYAxis(0, 1, "FEC (false/true)", kBottomMargin, kTopMargin);
@@ -1520,16 +1830,14 @@
void EventLogAnalyzer::CreateAudioEncoderEnableDtxGraph(Plot* plot) {
TimeSeries time_series("Audio encoder DTX", LineStyle::kLine,
PointStyle::kHighlight);
- auto GetAnaDtxEnabled =
- [](const LoggedAudioNetworkAdaptationEvent& ana_event) {
+ ProcessPoints<AudioNetworkAdaptationEvent>(
+ [](const AudioNetworkAdaptationEvent& ana_event) {
if (ana_event.config.enable_dtx)
return rtc::Optional<float>(
static_cast<float>(*ana_event.config.enable_dtx));
return rtc::Optional<float>();
- };
- ProcessPoints<LoggedAudioNetworkAdaptationEvent>(
- GetAnaDtxEnabled, parsed_log_.audio_network_adaptation_events(),
- begin_time_, &time_series);
+ },
+ audio_network_adaptation_events_, begin_time_, &time_series);
plot->AppendTimeSeries(std::move(time_series));
plot->SetXAxis(0, call_duration_s_, "Time (s)", kLeftMargin, kRightMargin);
plot->SetSuggestedYAxis(0, 1, "DTX (false/true)", kBottomMargin, kTopMargin);
@@ -1539,16 +1847,14 @@
void EventLogAnalyzer::CreateAudioEncoderNumChannelsGraph(Plot* plot) {
TimeSeries time_series("Audio encoder number of channels", LineStyle::kLine,
PointStyle::kHighlight);
- auto GetAnaNumChannels =
- [](const LoggedAudioNetworkAdaptationEvent& ana_event) {
+ ProcessPoints<AudioNetworkAdaptationEvent>(
+ [](const AudioNetworkAdaptationEvent& ana_event) {
if (ana_event.config.num_channels)
return rtc::Optional<float>(
static_cast<float>(*ana_event.config.num_channels));
return rtc::Optional<float>();
- };
- ProcessPoints<LoggedAudioNetworkAdaptationEvent>(
- GetAnaNumChannels, parsed_log_.audio_network_adaptation_events(),
- begin_time_, &time_series);
+ },
+ audio_network_adaptation_events_, begin_time_, &time_series);
plot->AppendTimeSeries(std::move(time_series));
plot->SetXAxis(0, call_duration_s_, "Time (s)", kLeftMargin, kRightMargin);
plot->SetSuggestedYAxis(0, 1, "Number of channels (1 (mono)/2 (stereo))",
@@ -1560,9 +1866,9 @@
public:
// Does not take any ownership, and all pointers must refer to valid objects
// that outlive the one constructed.
- NetEqStreamInput(const std::vector<LoggedRtpPacketIncoming>* packet_stream,
- const std::vector<int64_t>* output_events_us,
- rtc::Optional<int64_t> end_time_us)
+ NetEqStreamInput(const std::vector<LoggedRtpPacket>* packet_stream,
+ const std::vector<uint64_t>* output_events_us,
+ rtc::Optional<uint64_t> end_time_us)
: packet_stream_(*packet_stream),
packet_stream_it_(packet_stream_.begin()),
output_events_us_it_(output_events_us->begin()),
@@ -1576,11 +1882,11 @@
if (packet_stream_it_ == packet_stream_.end()) {
return rtc::nullopt;
}
- if (end_time_us_ && packet_stream_it_->rtp.log_time_us() > *end_time_us_) {
+ if (end_time_us_ && packet_stream_it_->timestamp > *end_time_us_) {
return rtc::nullopt;
}
// Convert from us to ms.
- return packet_stream_it_->rtp.log_time_us() / 1000;
+ return packet_stream_it_->timestamp / 1000;
}
rtc::Optional<int64_t> NextOutputEventTime() const override {
@@ -1599,14 +1905,14 @@
return std::unique_ptr<PacketData>();
}
std::unique_ptr<PacketData> packet_data(new PacketData());
- packet_data->header = packet_stream_it_->rtp.header;
+ packet_data->header = packet_stream_it_->header;
// Convert from us to ms.
- packet_data->time_ms = packet_stream_it_->rtp.log_time_us() / 1000.0;
+ packet_data->time_ms = packet_stream_it_->timestamp / 1000.0;
// This is a header-only "dummy" packet. Set the payload to all zeros, with
// length according to the virtual length.
- packet_data->payload.SetSize(packet_stream_it_->rtp.total_length -
- packet_stream_it_->rtp.header_length);
+ packet_data->payload.SetSize(packet_stream_it_->total_length -
+ packet_stream_it_->header_length);
std::fill_n(packet_data->payload.data(), packet_data->payload.size(), 0);
++packet_stream_it_;
@@ -1625,15 +1931,15 @@
if (packet_stream_it_ == packet_stream_.end()) {
return rtc::nullopt;
}
- return packet_stream_it_->rtp.header;
+ return packet_stream_it_->header;
}
private:
- const std::vector<LoggedRtpPacketIncoming>& packet_stream_;
- std::vector<LoggedRtpPacketIncoming>::const_iterator packet_stream_it_;
- std::vector<int64_t>::const_iterator output_events_us_it_;
- const std::vector<int64_t>::const_iterator output_events_us_end_;
- const rtc::Optional<int64_t> end_time_us_;
+ const std::vector<LoggedRtpPacket>& packet_stream_;
+ std::vector<LoggedRtpPacket>::const_iterator packet_stream_it_;
+ std::vector<uint64_t>::const_iterator output_events_us_it_;
+ const std::vector<uint64_t>::const_iterator output_events_us_end_;
+ const rtc::Optional<uint64_t> end_time_us_;
};
namespace {
@@ -1641,9 +1947,9 @@
// the test and returns the NetEqDelayAnalyzer object that was used to
// instrument the test.
std::unique_ptr<test::NetEqDelayAnalyzer> CreateNetEqTestAndRun(
- const std::vector<LoggedRtpPacketIncoming>* packet_stream,
- const std::vector<int64_t>* output_events_us,
- rtc::Optional<int64_t> end_time_us,
+ const std::vector<LoggedRtpPacket>* packet_stream,
+ const std::vector<uint64_t>* output_events_us,
+ rtc::Optional<uint64_t> end_time_us,
const std::string& replacement_file_name,
int file_sample_rate_hz) {
std::unique_ptr<test::NetEqInput> input(
@@ -1698,35 +2004,34 @@
const std::string& replacement_file_name,
int file_sample_rate_hz,
Plot* plot) {
- const std::vector<LoggedRtpPacketIncoming>* audio_packets = nullptr;
- uint32_t ssrc;
- for (const auto& stream : parsed_log_.incoming_rtp_packets_by_ssrc()) {
- if (IsAudioSsrc(kIncomingPacket, stream.ssrc)) {
- audio_packets = &stream.incoming_packets;
- ssrc = stream.ssrc;
- break;
- }
- }
- if (audio_packets == nullptr) {
+ const auto& incoming_audio_kv = std::find_if(
+ rtp_packets_.begin(), rtp_packets_.end(),
+ [this](std::pair<StreamId, std::vector<LoggedRtpPacket>> kv) {
+ return kv.first.GetDirection() == kIncomingPacket &&
+ this->IsAudioSsrc(kv.first);
+ });
+ if (incoming_audio_kv == rtp_packets_.end()) {
// No incoming audio stream found.
return;
}
- std::map<uint32_t, std::vector<int64_t>>::const_iterator output_events_it =
- parsed_log_.audio_playout_events().find(ssrc);
- if (output_events_it == parsed_log_.audio_playout_events().end()) {
+ const uint32_t ssrc = incoming_audio_kv->first.GetSsrc();
+
+ std::map<uint32_t, std::vector<uint64_t>>::const_iterator output_events_it =
+ audio_playout_events_.find(ssrc);
+ if (output_events_it == audio_playout_events_.end()) {
// Could not find output events with SSRC matching the input audio stream.
// Using the first available stream of output events.
- output_events_it = parsed_log_.audio_playout_events().cbegin();
+ output_events_it = audio_playout_events_.cbegin();
}
- rtc::Optional<int64_t> end_time_us =
+ rtc::Optional<uint64_t> end_time_us =
log_segments_.empty()
? rtc::nullopt
- : rtc::Optional<int64_t>(log_segments_.front().second);
+ : rtc::Optional<uint64_t>(log_segments_.front().second);
auto delay_cb = CreateNetEqTestAndRun(
- audio_packets, &output_events_it->second, end_time_us,
+ &incoming_audio_kv->second, &output_events_it->second, end_time_us,
replacement_file_name, file_sample_rate_hz);
std::vector<float> send_times_s;
@@ -1742,27 +2047,28 @@
RTC_DCHECK_EQ(send_times_s.size(), playout_delay_ms.size());
RTC_DCHECK_EQ(send_times_s.size(), target_delay_ms.size());
- std::map<uint32_t, TimeSeries> time_series_packet_arrival;
- std::map<uint32_t, TimeSeries> time_series_relative_packet_arrival;
- std::map<uint32_t, TimeSeries> time_series_play_time;
- std::map<uint32_t, TimeSeries> time_series_target_time;
+ std::map<StreamId, TimeSeries> time_series_packet_arrival;
+ std::map<StreamId, TimeSeries> time_series_relative_packet_arrival;
+ std::map<StreamId, TimeSeries> time_series_play_time;
+ std::map<StreamId, TimeSeries> time_series_target_time;
float min_y_axis = 0.f;
float max_y_axis = 0.f;
+ const StreamId stream_id = incoming_audio_kv->first;
for (size_t i = 0; i < send_times_s.size(); ++i) {
- time_series_packet_arrival[ssrc].points.emplace_back(
+ time_series_packet_arrival[stream_id].points.emplace_back(
TimeSeriesPoint(send_times_s[i], arrival_delay_ms[i]));
- time_series_relative_packet_arrival[ssrc].points.emplace_back(
+ time_series_relative_packet_arrival[stream_id].points.emplace_back(
TimeSeriesPoint(send_times_s[i], corrected_arrival_delay_ms[i]));
min_y_axis = std::min(min_y_axis, corrected_arrival_delay_ms[i]);
max_y_axis = std::max(max_y_axis, corrected_arrival_delay_ms[i]);
if (playout_delay_ms[i]) {
- time_series_play_time[ssrc].points.emplace_back(
+ time_series_play_time[stream_id].points.emplace_back(
TimeSeriesPoint(send_times_s[i], *playout_delay_ms[i]));
min_y_axis = std::min(min_y_axis, *playout_delay_ms[i]);
max_y_axis = std::max(max_y_axis, *playout_delay_ms[i]);
}
if (target_delay_ms[i]) {
- time_series_target_time[ssrc].points.emplace_back(
+ time_series_target_time[stream_id].points.emplace_back(
TimeSeriesPoint(send_times_s[i], *target_delay_ms[i]));
min_y_axis = std::min(min_y_axis, *target_delay_ms[i]);
max_y_axis = std::max(max_y_axis, *target_delay_ms[i]);
@@ -1800,7 +2106,7 @@
void EventLogAnalyzer::CreateIceCandidatePairConfigGraph(Plot* plot) {
std::map<uint32_t, TimeSeries> configs_by_cp_id;
- for (const auto& config : parsed_log_.ice_candidate_pair_configs()) {
+ 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 =
@@ -1812,7 +2118,7 @@
candidate_pair_desc_by_id_[config.candidate_pair_id] =
candidate_pair_desc;
}
- float x = ToCallTime(config.log_time_us());
+ 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);
}
@@ -1836,7 +2142,7 @@
candidate_pair_desc_by_id_.end()) {
return candidate_pair_desc_by_id_[candidate_pair_id];
}
- for (const auto& config : parsed_log_.ice_candidate_pair_configs()) {
+ 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) ==
@@ -1852,7 +2158,7 @@
void EventLogAnalyzer::CreateIceConnectivityCheckGraph(Plot* plot) {
std::map<uint32_t, TimeSeries> checks_by_cp_id;
- for (const auto& event : parsed_log_.ice_candidate_pair_events()) {
+ 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(
@@ -1860,7 +2166,7 @@
GetCandidatePairLogDescriptionFromId(event.candidate_pair_id),
LineStyle::kNone, PointStyle::kHighlight);
}
- float x = ToCallTime(event.log_time_us());
+ 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);
}
@@ -1876,176 +2182,163 @@
plot->SetTitle("[IceEventLog] ICE connectivity checks");
}
+void EventLogAnalyzer::Notification(
+ std::unique_ptr<TriageNotification> notification) {
+ notifications_.push_back(std::move(notification));
+}
+
void EventLogAnalyzer::PrintNotifications(FILE* file) {
+ if (notifications_.size() == 0)
+ return;
fprintf(file, "========== TRIAGE NOTIFICATIONS ==========\n");
- for (const auto& alert : incoming_rtp_recv_time_gaps_) {
- fprintf(file, "%3.3lf s : %s\n", alert.Time(), alert.ToString().c_str());
- }
- for (const auto& alert : incoming_rtcp_recv_time_gaps_) {
- fprintf(file, "%3.3lf s : %s\n", alert.Time(), alert.ToString().c_str());
- }
- for (const auto& alert : outgoing_rtp_send_time_gaps_) {
- fprintf(file, "%3.3lf s : %s\n", alert.Time(), alert.ToString().c_str());
- }
- for (const auto& alert : outgoing_rtcp_send_time_gaps_) {
- fprintf(file, "%3.3lf s : %s\n", alert.Time(), alert.ToString().c_str());
- }
- for (const auto& alert : incoming_seq_num_jumps_) {
- fprintf(file, "%3.3lf s : %s\n", alert.Time(), alert.ToString().c_str());
- }
- for (const auto& alert : incoming_capture_time_jumps_) {
- fprintf(file, "%3.3lf s : %s\n", alert.Time(), alert.ToString().c_str());
- }
- for (const auto& alert : outgoing_seq_num_jumps_) {
- fprintf(file, "%3.3lf s : %s\n", alert.Time(), alert.ToString().c_str());
- }
- for (const auto& alert : outgoing_capture_time_jumps_) {
- fprintf(file, "%3.3lf s : %s\n", alert.Time(), alert.ToString().c_str());
- }
- for (const auto& alert : outgoing_high_loss_alerts_) {
- fprintf(file, " : %s\n", alert.ToString().c_str());
+ for (const auto& notification : notifications_) {
+ rtc::Optional<float> call_timestamp = notification->Time();
+ if (call_timestamp.has_value()) {
+ fprintf(file, "%3.3lf s : %s\n", call_timestamp.value(),
+ notification->ToString().c_str());
+ } else {
+ fprintf(file, " : %s\n", notification->ToString().c_str());
+ }
}
fprintf(file, "========== END TRIAGE NOTIFICATIONS ==========\n");
}
-void EventLogAnalyzer::CreateStreamGapAlerts(PacketDirection direction) {
- // With 100 packets/s (~800kbps), false positives would require 10 s without
- // data.
- constexpr int64_t kMaxSeqNumJump = 1000;
- // With a 90 kHz clock, false positives would require 10 s without data.
- constexpr int64_t kMaxCaptureTimeJump = 900000;
-
- int64_t end_time_us = log_segments_.empty()
- ? std::numeric_limits<int64_t>::max()
- : log_segments_.front().second;
-
- SeqNumUnwrapper<uint16_t> seq_num_unwrapper;
- rtc::Optional<int64_t> last_seq_num;
- SeqNumUnwrapper<uint32_t> capture_time_unwrapper;
- rtc::Optional<int64_t> last_capture_time;
- // Check for gaps in sequence numbers and capture timestamps.
- for (const auto& stream : parsed_log_.rtp_packets_by_ssrc(direction)) {
- for (const auto& packet : stream.packet_view) {
- if (packet.log_time_us() > end_time_us) {
- // Only process the first (LOG_START, LOG_END) segment.
- break;
- }
-
- int64_t seq_num = seq_num_unwrapper.Unwrap(packet.header.sequenceNumber);
- if (last_seq_num.has_value() &&
- std::abs(seq_num - last_seq_num.value()) > kMaxSeqNumJump) {
- Alert_SeqNumJump(direction, ToCallTime(packet.log_time_us()),
- packet.header.ssrc);
- }
- last_seq_num.emplace(seq_num);
-
- int64_t capture_time =
- capture_time_unwrapper.Unwrap(packet.header.timestamp);
- if (last_capture_time.has_value() &&
- std::abs(capture_time - last_capture_time.value()) >
- kMaxCaptureTimeJump) {
- Alert_CaptureTimeJump(direction, ToCallTime(packet.log_time_us()),
- packet.header.ssrc);
- }
- last_capture_time.emplace(capture_time);
- }
- }
-}
-
-void EventLogAnalyzer::CreateTransmissionGapAlerts(PacketDirection direction) {
- constexpr int64_t kMaxRtpTransmissionGap = 500000;
- constexpr int64_t kMaxRtcpTransmissionGap = 2000000;
- int64_t end_time_us = log_segments_.empty()
- ? std::numeric_limits<int64_t>::max()
- : log_segments_.front().second;
-
- // TODO(terelius): The parser could provide a list of all packets, ordered
- // by time, for each direction.
- std::multimap<int64_t, const LoggedRtpPacket*> rtp_in_direction;
- for (const auto& stream : parsed_log_.rtp_packets_by_ssrc(direction)) {
- for (const LoggedRtpPacket& rtp_packet : stream.packet_view)
- rtp_in_direction.emplace(rtp_packet.log_time_us(), &rtp_packet);
- }
- rtc::Optional<int64_t> last_rtp_time;
- for (const auto& kv : rtp_in_direction) {
- int64_t timestamp = kv.first;
- if (timestamp > end_time_us) {
- // Only process the first (LOG_START, LOG_END) segment.
- break;
- }
- int64_t duration = timestamp - last_rtp_time.value_or(0);
- if (last_rtp_time.has_value() && duration > kMaxRtpTransmissionGap) {
- // No packet sent/received for more than 500 ms.
- Alert_RtpLogTimeGap(direction, ToCallTime(timestamp), duration / 1000);
- }
- last_rtp_time.emplace(timestamp);
- }
-
- rtc::Optional<int64_t> last_rtcp_time;
- if (direction == kIncomingPacket) {
- for (const auto& rtcp : parsed_log_.incoming_rtcp_packets()) {
- if (rtcp.log_time_us() > end_time_us) {
- // Only process the first (LOG_START, LOG_END) segment.
- break;
- }
- int64_t duration = rtcp.log_time_us() - last_rtcp_time.value_or(0);
- if (last_rtcp_time.has_value() && duration > kMaxRtcpTransmissionGap) {
- // No feedback sent/received for more than 2000 ms.
- Alert_RtcpLogTimeGap(direction, ToCallTime(rtcp.log_time_us()),
- duration / 1000);
- }
- last_rtcp_time.emplace(rtcp.log_time_us());
- }
- } else {
- for (const auto& rtcp : parsed_log_.outgoing_rtcp_packets()) {
- if (rtcp.log_time_us() > end_time_us) {
- // Only process the first (LOG_START, LOG_END) segment.
- break;
- }
- int64_t duration = rtcp.log_time_us() - last_rtcp_time.value_or(0);
- if (last_rtcp_time.has_value() && duration > kMaxRtcpTransmissionGap) {
- // No feedback sent/received for more than 2000 ms.
- Alert_RtcpLogTimeGap(direction, ToCallTime(rtcp.log_time_us()),
- duration / 1000);
- }
- last_rtcp_time.emplace(rtcp.log_time_us());
- }
- }
-}
-
// TODO(terelius): Notifications could possibly be generated by the same code
// that produces the graphs. There is some code duplication that could be
// avoided, but that might be solved anyway when we move functionality from the
// analyzer to the parser.
void EventLogAnalyzer::CreateTriageNotifications() {
- CreateStreamGapAlerts(kIncomingPacket);
- CreateStreamGapAlerts(kOutgoingPacket);
- CreateTransmissionGapAlerts(kIncomingPacket);
- CreateTransmissionGapAlerts(kOutgoingPacket);
+ uint64_t end_time_us = log_segments_.empty()
+ ? std::numeric_limits<uint64_t>::max()
+ : log_segments_.front().second;
+ // Check for gaps in sequence numbers and capture timestamps.
+ for (auto& kv : rtp_packets_) {
+ StreamId stream_id = kv.first;
+ const std::vector<LoggedRtpPacket>& packet_stream = kv.second;
- int64_t end_time_us = log_segments_.empty()
- ? std::numeric_limits<int64_t>::max()
- : log_segments_.front().second;
+ SeqNumUnwrapper<uint16_t> seq_no_unwrapper;
+ rtc::Optional<int64_t> last_seq_no;
+ SeqNumUnwrapper<uint32_t> timestamp_unwrapper;
+ rtc::Optional<int64_t> last_timestamp;
+ for (const auto& packet : packet_stream) {
+ if (packet.timestamp > end_time_us) {
+ // Only process the first (LOG_START, LOG_END) segment.
+ break;
+ }
+ int64_t seq_no = seq_no_unwrapper.Unwrap(packet.header.sequenceNumber);
+ if (last_seq_no.has_value() &&
+ std::abs(seq_no - last_seq_no.value()) > 1000) {
+ // With roughly 100 packets per second (~800kbps), this would require 10
+ // seconds without data to trigger incorrectly.
+ if (stream_id.GetDirection() == kIncomingPacket) {
+ Notification(rtc::MakeUnique<IncomingSeqNoJump>(
+ ToCallTime(packet.timestamp), packet.header.ssrc));
+ } else {
+ Notification(rtc::MakeUnique<OutgoingSeqNoJump>(
+ ToCallTime(packet.timestamp), packet.header.ssrc));
+ }
+ }
+ last_seq_no.emplace(seq_no);
+ int64_t timestamp = timestamp_unwrapper.Unwrap(packet.header.timestamp);
+ if (last_timestamp.has_value() &&
+ std::abs(timestamp - last_timestamp.value()) > 900000) {
+ // With a 90 kHz clock, this would require 10 seconds without data to
+ // trigger incorrectly.
+ if (stream_id.GetDirection() == kIncomingPacket) {
+ Notification(rtc::MakeUnique<IncomingCaptureTimeJump>(
+ ToCallTime(packet.timestamp), packet.header.ssrc));
+ } else {
+ Notification(rtc::MakeUnique<OutgoingCaptureTimeJump>(
+ ToCallTime(packet.timestamp), packet.header.ssrc));
+ }
+ }
+ last_timestamp.emplace(timestamp);
+ }
+ }
- constexpr double kMaxLossFraction = 0.05;
+ // Check for gaps in RTP and RTCP streams
+ for (const auto direction :
+ {PacketDirection::kIncomingPacket, PacketDirection::kOutgoingPacket}) {
+ // TODO(terelius): The parser could provide a list of all packets, ordered
+ // by time, for each direction.
+ std::multimap<uint64_t, const LoggedRtpPacket*> rtp_in_direction;
+ for (const auto& kv : rtp_packets_) {
+ if (kv.first.GetDirection() == direction) {
+ for (const LoggedRtpPacket& rtp_packet : kv.second)
+ rtp_in_direction.emplace(rtp_packet.timestamp, &rtp_packet);
+ }
+ }
+ rtc::Optional<uint64_t> last_rtp_packet;
+ for (const auto& kv : rtp_in_direction) {
+ uint64_t timestamp = kv.first;
+ if (timestamp > end_time_us) {
+ // Only process the first (LOG_START, LOG_END) segment.
+ break;
+ }
+ int64_t duration = timestamp - last_rtp_packet.value_or(0);
+ if (last_rtp_packet.has_value() && duration > 500000) {
+ // No incoming packet for more than 500 ms.
+ if (direction == kIncomingPacket) {
+ Notification(rtc::MakeUnique<IncomingRtpReceiveTimeGap>(
+ ToCallTime(timestamp), duration / 1000));
+ } else {
+ Notification(rtc::MakeUnique<OutgoingRtpSendTimeGap>(
+ ToCallTime(timestamp), duration / 1000));
+ }
+ }
+ last_rtp_packet.emplace(timestamp);
+ }
+
+ // TODO(terelius): The parser could provide a list of all packets, ordered
+ // by time, for each direction.
+ std::multimap<uint64_t, const LoggedRtcpPacket*> rtcp_in_direction;
+ for (const auto& kv : rtcp_packets_) {
+ if (kv.first.GetDirection() == direction) {
+ for (const LoggedRtcpPacket& rtcp_packet : kv.second)
+ rtcp_in_direction.emplace(rtcp_packet.timestamp, &rtcp_packet);
+ }
+ }
+ rtc::Optional<uint64_t> last_incoming_rtcp_packet;
+ for (const auto& kv : rtcp_in_direction) {
+ uint64_t timestamp = kv.first;
+ if (timestamp > end_time_us) {
+ // Only process the first (LOG_START, LOG_END) segment.
+ break;
+ }
+ int64_t duration = timestamp - last_incoming_rtcp_packet.value_or(0);
+ if (last_incoming_rtcp_packet.has_value() && duration > 2000000) {
+ // No incoming feedback for more than 2000 ms.
+ if (direction == kIncomingPacket) {
+ Notification(rtc::MakeUnique<IncomingRtcpReceiveTimeGap>(
+ ToCallTime(timestamp), duration / 1000));
+ } else {
+ Notification(rtc::MakeUnique<OutgoingRtcpSendTimeGap>(
+ ToCallTime(timestamp), duration / 1000));
+ }
+ }
+ last_incoming_rtcp_packet.emplace(timestamp);
+ }
+ }
+
// Loss feedback
int64_t total_lost_packets = 0;
int64_t total_expected_packets = 0;
- for (auto& bwe_update : parsed_log_.bwe_loss_updates()) {
- if (bwe_update.log_time_us() > end_time_us) {
+ for (auto& bwe_update : bwe_loss_updates_) {
+ if (bwe_update.timestamp > end_time_us) {
// Only process the first (LOG_START, LOG_END) segment.
break;
}
- int64_t lost_packets = static_cast<double>(bwe_update.fraction_lost) / 255 *
+ int64_t lost_packets = static_cast<double>(bwe_update.fraction_loss) / 255 *
bwe_update.expected_packets;
total_lost_packets += lost_packets;
total_expected_packets += bwe_update.expected_packets;
}
double avg_outgoing_loss =
static_cast<double>(total_lost_packets) / total_expected_packets;
- if (avg_outgoing_loss > kMaxLossFraction) {
- Alert_OutgoingHighLoss(avg_outgoing_loss);
+ if (avg_outgoing_loss > 0.05) {
+ Notification(rtc::MakeUnique<OutgoingHighLoss>(avg_outgoing_loss));
}
}
+} // namespace plotting
} // namespace webrtc
diff --git a/rtc_tools/event_log_visualizer/analyzer.h b/rtc_tools/event_log_visualizer/analyzer.h
index b37de21..a8fedb8 100644
--- a/rtc_tools/event_log_visualizer/analyzer.h
+++ b/rtc_tools/event_log_visualizer/analyzer.h
@@ -18,12 +18,54 @@
#include <utility>
#include <vector>
-#include "logging/rtc_event_log/rtc_event_log_parser2.h"
-#include "rtc_base/strings/string_builder.h"
+#include "logging/rtc_event_log/rtc_event_log_parser.h"
+#include "modules/audio_coding/audio_network_adaptor/include/audio_network_adaptor.h"
+#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
+#include "modules/rtp_rtcp/source/rtcp_packet.h"
+#include "rtc_base/function_view.h"
#include "rtc_tools/event_log_visualizer/plot_base.h"
#include "rtc_tools/event_log_visualizer/triage_notifications.h"
namespace webrtc {
+namespace plotting {
+
+struct LoggedRtpPacket {
+ LoggedRtpPacket(uint64_t timestamp,
+ RTPHeader header,
+ size_t header_length,
+ size_t total_length)
+ : timestamp(timestamp),
+ header(header),
+ header_length(header_length),
+ total_length(total_length) {}
+ uint64_t timestamp;
+ // TODO(terelius): This allocates space for 15 CSRCs even if none are used.
+ RTPHeader header;
+ size_t header_length;
+ size_t total_length;
+};
+
+struct LoggedRtcpPacket {
+ LoggedRtcpPacket(uint64_t timestamp,
+ RTCPPacketType rtcp_type,
+ std::unique_ptr<rtcp::RtcpPacket> rtcp_packet)
+ : timestamp(timestamp), type(rtcp_type), packet(std::move(rtcp_packet)) {}
+ uint64_t timestamp;
+ RTCPPacketType type;
+ std::unique_ptr<rtcp::RtcpPacket> packet;
+};
+
+struct LossBasedBweUpdate {
+ uint64_t timestamp;
+ int32_t new_bitrate;
+ uint8_t fraction_loss;
+ int32_t expected_packets;
+};
+
+struct AudioNetworkAdaptationEvent {
+ uint64_t timestamp;
+ AudioEncoderRuntimeConfig config;
+};
class EventLogAnalyzer {
public:
@@ -32,13 +74,14 @@
// modified while the EventLogAnalyzer is being used.
explicit EventLogAnalyzer(const ParsedRtcEventLog& log);
- void CreatePacketGraph(PacketDirection direction, Plot* plot);
+ void CreatePacketGraph(PacketDirection desired_direction, Plot* plot);
- void CreateAccumulatedPacketsGraph(PacketDirection direction, Plot* plot);
+ void CreateAccumulatedPacketsGraph(PacketDirection desired_direction,
+ Plot* plot);
void CreatePlayoutGraph(Plot* plot);
- void CreateAudioLevelGraph(PacketDirection direction, Plot* plot);
+ void CreateAudioLevelGraph(Plot* plot);
void CreateSequenceNumberGraph(Plot* plot);
@@ -49,20 +92,19 @@
void CreateFractionLossGraph(Plot* plot);
- void CreateTotalIncomingBitrateGraph(Plot* plot);
- void CreateTotalOutgoingBitrateGraph(Plot* plot,
- bool show_detector_state = false,
- bool show_alr_state = false);
+ void CreateTotalBitrateGraph(PacketDirection desired_direction,
+ Plot* plot,
+ bool show_detector_state = false,
+ bool show_alr_state = false);
- void CreateStreamBitrateGraph(PacketDirection direction, Plot* plot);
+ void CreateStreamBitrateGraph(PacketDirection desired_direction, Plot* plot);
void CreateSendSideBweSimulationGraph(Plot* plot);
void CreateReceiveSideBweSimulationGraph(Plot* plot);
void CreateNetworkDelayFeedbackGraph(Plot* plot);
void CreatePacerDelayGraph(Plot* plot);
-
- void CreateTimestampGraph(PacketDirection direction, Plot* plot);
+ void CreateTimestampGraph(Plot* plot);
void CreateAudioEncoderTargetBitrateGraph(Plot* plot);
void CreateAudioEncoderFrameLengthGraph(Plot* plot);
@@ -77,114 +119,55 @@
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;
+
void CreateTriageNotifications();
void PrintNotifications(FILE* file);
private:
- bool IsRtxSsrc(PacketDirection direction, uint32_t ssrc) const {
- if (direction == kIncomingPacket) {
- return parsed_log_.incoming_rtx_ssrcs().find(ssrc) !=
- parsed_log_.incoming_rtx_ssrcs().end();
- } else {
- return parsed_log_.outgoing_rtx_ssrcs().find(ssrc) !=
- parsed_log_.outgoing_rtx_ssrcs().end();
+ class StreamId {
+ public:
+ StreamId(uint32_t ssrc, webrtc::PacketDirection direction)
+ : ssrc_(ssrc), direction_(direction) {}
+ bool operator<(const StreamId& other) const {
+ return std::tie(ssrc_, direction_) <
+ std::tie(other.ssrc_, other.direction_);
}
- }
-
- bool IsVideoSsrc(PacketDirection direction, uint32_t ssrc) const {
- if (direction == kIncomingPacket) {
- return parsed_log_.incoming_video_ssrcs().find(ssrc) !=
- parsed_log_.incoming_video_ssrcs().end();
- } else {
- return parsed_log_.outgoing_video_ssrcs().find(ssrc) !=
- parsed_log_.outgoing_video_ssrcs().end();
+ bool operator==(const StreamId& other) const {
+ return std::tie(ssrc_, direction_) ==
+ std::tie(other.ssrc_, other.direction_);
}
- }
+ uint32_t GetSsrc() const { return ssrc_; }
+ webrtc::PacketDirection GetDirection() const { return direction_; }
- bool IsAudioSsrc(PacketDirection direction, uint32_t ssrc) const {
- if (direction == kIncomingPacket) {
- return parsed_log_.incoming_audio_ssrcs().find(ssrc) !=
- parsed_log_.incoming_audio_ssrcs().end();
- } else {
- return parsed_log_.outgoing_audio_ssrcs().find(ssrc) !=
- parsed_log_.outgoing_audio_ssrcs().end();
- }
- }
+ private:
+ uint32_t ssrc_;
+ webrtc::PacketDirection direction_;
+ };
- template <typename IterableType>
- void CreateAccumulatedPacketsTimeSeries(Plot* plot,
- const IterableType& packets,
- const std::string& label);
+ template <typename T>
+ void CreateAccumulatedPacketsTimeSeries(
+ PacketDirection desired_direction,
+ Plot* plot,
+ const std::map<StreamId, std::vector<T>>& packets,
+ const std::string& label_prefix);
- void CreateStreamGapAlerts(PacketDirection direction);
- void CreateTransmissionGapAlerts(PacketDirection direction);
+ bool IsRtxSsrc(StreamId stream_id) const;
- std::string GetStreamName(PacketDirection direction, uint32_t ssrc) const {
- char buffer[200];
- rtc::SimpleStringBuilder name(buffer);
- if (IsAudioSsrc(direction, ssrc)) {
- name << "Audio ";
- } else if (IsVideoSsrc(direction, ssrc)) {
- name << "Video ";
- } else {
- name << "Unknown ";
- }
- if (IsRtxSsrc(direction, ssrc)) {
- name << "RTX ";
- }
- if (direction == kIncomingPacket)
- name << "(In) ";
- else
- name << "(Out) ";
- name << "SSRC " << ssrc;
- return name.str();
- }
+ bool IsVideoSsrc(StreamId stream_id) const;
+
+ bool IsAudioSsrc(StreamId stream_id) const;
+
+ std::string GetStreamName(StreamId stream_id) const;
+
+ rtc::Optional<uint32_t> EstimateRtpClockFrequency(
+ const std::vector<LoggedRtpPacket>& packets) const;
float ToCallTime(int64_t timestamp) const;
- void Alert_RtpLogTimeGap(PacketDirection direction,
- float time_seconds,
- int64_t duration) {
- if (direction == kIncomingPacket) {
- incoming_rtp_recv_time_gaps_.emplace_back(time_seconds, duration);
- } else {
- outgoing_rtp_send_time_gaps_.emplace_back(time_seconds, duration);
- }
- }
-
- void Alert_RtcpLogTimeGap(PacketDirection direction,
- float time_seconds,
- int64_t duration) {
- if (direction == kIncomingPacket) {
- incoming_rtcp_recv_time_gaps_.emplace_back(time_seconds, duration);
- } else {
- outgoing_rtcp_send_time_gaps_.emplace_back(time_seconds, duration);
- }
- }
-
- void Alert_SeqNumJump(PacketDirection direction,
- float time_seconds,
- uint32_t ssrc) {
- if (direction == kIncomingPacket) {
- incoming_seq_num_jumps_.emplace_back(time_seconds, ssrc);
- } else {
- outgoing_seq_num_jumps_.emplace_back(time_seconds, ssrc);
- }
- }
-
- void Alert_CaptureTimeJump(PacketDirection direction,
- float time_seconds,
- uint32_t ssrc) {
- if (direction == kIncomingPacket) {
- incoming_capture_time_jumps_.emplace_back(time_seconds, ssrc);
- } else {
- outgoing_capture_time_jumps_.emplace_back(time_seconds, ssrc);
- }
- }
-
- void Alert_OutgoingHighLoss(double avg_loss_fraction) {
- outgoing_high_loss_alerts_.emplace_back(avg_loss_fraction);
- }
+ void Notification(std::unique_ptr<TriageNotification> notification);
std::string GetCandidatePairLogDescriptionFromId(uint32_t candidate_pair_id);
@@ -194,19 +177,50 @@
// If left empty, all SSRCs will be considered relevant.
std::vector<uint32_t> desired_ssrc_;
+ // Tracks what each stream is configured for. Note that a single SSRC can be
+ // in several sets. For example, the SSRC used for sending video over RTX
+ // will appear in both video_ssrcs_ and rtx_ssrcs_. In the unlikely case that
+ // an SSRC is reconfigured to a different media type mid-call, it will also
+ // appear in multiple sets.
+ std::set<StreamId> rtx_ssrcs_;
+ std::set<StreamId> video_ssrcs_;
+ std::set<StreamId> audio_ssrcs_;
+
+ // Maps a stream identifier consisting of ssrc and direction to the parsed
+ // RTP headers in that stream. Header extensions are parsed if the stream
+ // has been configured.
+ std::map<StreamId, std::vector<LoggedRtpPacket>> rtp_packets_;
+
+ std::map<StreamId, std::vector<LoggedRtcpPacket>> rtcp_packets_;
+
+ // Maps an SSRC to the timestamps of parsed audio playout events.
+ std::map<uint32_t, std::vector<uint64_t>> audio_playout_events_;
+
// Stores the timestamps for all log segments, in the form of associated start
// and end events.
- std::vector<std::pair<int64_t, int64_t>> log_segments_;
+ std::vector<std::pair<uint64_t, uint64_t>> log_segments_;
- std::vector<IncomingRtpReceiveTimeGap> incoming_rtp_recv_time_gaps_;
- std::vector<IncomingRtcpReceiveTimeGap> incoming_rtcp_recv_time_gaps_;
- std::vector<OutgoingRtpSendTimeGap> outgoing_rtp_send_time_gaps_;
- std::vector<OutgoingRtcpSendTimeGap> outgoing_rtcp_send_time_gaps_;
- std::vector<IncomingSeqNumJump> incoming_seq_num_jumps_;
- std::vector<IncomingCaptureTimeJump> incoming_capture_time_jumps_;
- std::vector<OutgoingSeqNoJump> outgoing_seq_num_jumps_;
- std::vector<OutgoingCaptureTimeJump> outgoing_capture_time_jumps_;
- std::vector<OutgoingHighLoss> outgoing_high_loss_alerts_;
+ // A list of all updates from the send-side loss-based bandwidth estimator.
+ std::vector<LossBasedBweUpdate> bwe_loss_updates_;
+
+ std::vector<AudioNetworkAdaptationEvent> audio_network_adaptation_events_;
+
+ std::vector<ParsedRtcEventLog::BweProbeClusterCreatedEvent>
+ bwe_probe_cluster_created_events_;
+
+ std::vector<ParsedRtcEventLog::BweProbeResultEvent> bwe_probe_result_events_;
+
+ std::vector<ParsedRtcEventLog::BweDelayBasedUpdate> bwe_delay_updates_;
+
+ std::vector<std::unique_ptr<TriageNotification>> notifications_;
+
+ 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_;
@@ -214,17 +228,18 @@
// The generated data points will be |step_| microseconds apart.
// Only events occuring at most |window_duration_| microseconds before the
// current data point will be part of the average.
- int64_t window_duration_;
- int64_t step_;
+ uint64_t window_duration_;
+ uint64_t step_;
// First and last events of the log.
- int64_t begin_time_;
- int64_t end_time_;
+ uint64_t begin_time_;
+ uint64_t end_time_;
// Duration (in seconds) of log file.
float call_duration_s_;
};
+} // namespace plotting
} // namespace webrtc
#endif // RTC_TOOLS_EVENT_LOG_VISUALIZER_ANALYZER_H_
diff --git a/rtc_tools/event_log_visualizer/main.cc b/rtc_tools/event_log_visualizer/main.cc
index 3dce290..2e7a79e 100644
--- a/rtc_tools/event_log_visualizer/main.cc
+++ b/rtc_tools/event_log_visualizer/main.cc
@@ -10,7 +10,7 @@
#include <iostream>
-#include "logging/rtc_event_log/rtc_event_log_parser2.h"
+#include "logging/rtc_event_log/rtc_event_log_parser.h"
#include "rtc_base/flags.h"
#include "rtc_tools/event_log_visualizer/analyzer.h"
#include "rtc_tools/event_log_visualizer/plot_base.h"
@@ -143,15 +143,10 @@
false,
"Show the state ALR state on the total bitrate graph");
-DEFINE_bool(parse_unconfigured_header_extensions,
- true,
- "Attempt to parse unconfigured header extensions using the default "
- "WebRTC mapping. This can give very misleading results if the "
- "application negotiates a different mapping.");
-
-DEFINE_bool(print_triage_alerts,
- false,
- "Print triage alerts, i.e. a list of potential problems.");
+DEFINE_bool(
+ print_triage_notifications,
+ false,
+ "Print triage notifications, i.e. a list of suspicious looking events.");
void SetAllPlotFlags(bool setting);
@@ -214,13 +209,7 @@
std::string filename = argv[1];
- webrtc::ParsedRtcEventLog::UnconfiguredHeaderExtensions header_extensions =
- webrtc::ParsedRtcEventLog::UnconfiguredHeaderExtensions::kDontParse;
- if (FLAG_parse_unconfigured_header_extensions) {
- header_extensions = webrtc::ParsedRtcEventLog::
- UnconfiguredHeaderExtensions::kAttemptWebrtcDefaultConfig;
- }
- webrtc::ParsedRtcEventLog parsed_log(header_extensions);
+ webrtc::ParsedRtcEventLog parsed_log;
if (!parsed_log.ParseFile(filename)) {
std::cerr << "Could not parse the entire log file." << std::endl;
@@ -229,34 +218,31 @@
<< std::endl;
}
- webrtc::EventLogAnalyzer analyzer(parsed_log);
- std::unique_ptr<webrtc::PlotCollection> collection(
- new webrtc::PythonPlotCollection());
+ webrtc::plotting::EventLogAnalyzer analyzer(parsed_log);
+ std::unique_ptr<webrtc::plotting::PlotCollection> collection(
+ new webrtc::plotting::PythonPlotCollection());
if (FLAG_plot_incoming_packet_sizes) {
- analyzer.CreatePacketGraph(webrtc::kIncomingPacket,
+ analyzer.CreatePacketGraph(webrtc::PacketDirection::kIncomingPacket,
collection->AppendNewPlot());
}
if (FLAG_plot_outgoing_packet_sizes) {
- analyzer.CreatePacketGraph(webrtc::kOutgoingPacket,
+ analyzer.CreatePacketGraph(webrtc::PacketDirection::kOutgoingPacket,
collection->AppendNewPlot());
}
if (FLAG_plot_incoming_packet_count) {
- analyzer.CreateAccumulatedPacketsGraph(webrtc::kIncomingPacket,
- collection->AppendNewPlot());
+ analyzer.CreateAccumulatedPacketsGraph(
+ webrtc::PacketDirection::kIncomingPacket, collection->AppendNewPlot());
}
if (FLAG_plot_outgoing_packet_count) {
- analyzer.CreateAccumulatedPacketsGraph(webrtc::kOutgoingPacket,
- collection->AppendNewPlot());
+ analyzer.CreateAccumulatedPacketsGraph(
+ webrtc::PacketDirection::kOutgoingPacket, collection->AppendNewPlot());
}
if (FLAG_plot_audio_playout) {
analyzer.CreatePlayoutGraph(collection->AppendNewPlot());
}
if (FLAG_plot_audio_level) {
- analyzer.CreateAudioLevelGraph(webrtc::kIncomingPacket,
- collection->AppendNewPlot());
- analyzer.CreateAudioLevelGraph(webrtc::kOutgoingPacket,
- collection->AppendNewPlot());
+ analyzer.CreateAudioLevelGraph(collection->AppendNewPlot());
}
if (FLAG_plot_incoming_sequence_number_delta) {
analyzer.CreateSequenceNumberGraph(collection->AppendNewPlot());
@@ -271,19 +257,23 @@
analyzer.CreateIncomingPacketLossGraph(collection->AppendNewPlot());
}
if (FLAG_plot_incoming_bitrate) {
- analyzer.CreateTotalIncomingBitrateGraph(collection->AppendNewPlot());
+ analyzer.CreateTotalBitrateGraph(webrtc::PacketDirection::kIncomingPacket,
+ collection->AppendNewPlot(),
+ FLAG_show_detector_state,
+ FLAG_show_alr_state);
}
if (FLAG_plot_outgoing_bitrate) {
- analyzer.CreateTotalOutgoingBitrateGraph(collection->AppendNewPlot(),
- FLAG_show_detector_state,
- FLAG_show_alr_state);
+ analyzer.CreateTotalBitrateGraph(webrtc::PacketDirection::kOutgoingPacket,
+ collection->AppendNewPlot(),
+ FLAG_show_detector_state,
+ FLAG_show_alr_state);
}
if (FLAG_plot_incoming_stream_bitrate) {
- analyzer.CreateStreamBitrateGraph(webrtc::kIncomingPacket,
+ analyzer.CreateStreamBitrateGraph(webrtc::PacketDirection::kIncomingPacket,
collection->AppendNewPlot());
}
if (FLAG_plot_outgoing_stream_bitrate) {
- analyzer.CreateStreamBitrateGraph(webrtc::kOutgoingPacket,
+ analyzer.CreateStreamBitrateGraph(webrtc::PacketDirection::kOutgoingPacket,
collection->AppendNewPlot());
}
if (FLAG_plot_simulated_receiveside_bwe) {
@@ -299,10 +289,7 @@
analyzer.CreateFractionLossGraph(collection->AppendNewPlot());
}
if (FLAG_plot_timestamps) {
- analyzer.CreateTimestampGraph(webrtc::kIncomingPacket,
- collection->AppendNewPlot());
- analyzer.CreateTimestampGraph(webrtc::kOutgoingPacket,
- collection->AppendNewPlot());
+ analyzer.CreateTimestampGraph(collection->AppendNewPlot());
}
if (FLAG_plot_pacer_delay) {
analyzer.CreatePacerDelayGraph(collection->AppendNewPlot());
@@ -346,7 +333,7 @@
collection->Draw();
- if (FLAG_print_triage_alerts) {
+ if (FLAG_print_triage_notifications) {
analyzer.CreateTriageNotifications();
analyzer.PrintNotifications(stderr);
}
diff --git a/rtc_tools/event_log_visualizer/plot_base.cc b/rtc_tools/event_log_visualizer/plot_base.cc
index 9a21393..7ff4ef9 100644
--- a/rtc_tools/event_log_visualizer/plot_base.cc
+++ b/rtc_tools/event_log_visualizer/plot_base.cc
@@ -15,6 +15,7 @@
#include "rtc_base/checks.h"
namespace webrtc {
+namespace plotting {
void Plot::SetXAxis(float min_value,
float max_value,
@@ -84,4 +85,5 @@
}
}
+} // namespace plotting
} // namespace webrtc
diff --git a/rtc_tools/event_log_visualizer/plot_base.h b/rtc_tools/event_log_visualizer/plot_base.h
index e73f004..700ffbf 100644
--- a/rtc_tools/event_log_visualizer/plot_base.h
+++ b/rtc_tools/event_log_visualizer/plot_base.h
@@ -16,6 +16,7 @@
#include <vector>
namespace webrtc {
+namespace plotting {
enum class LineStyle {
kNone, // No line connecting the points. Used to create scatter plots.
@@ -172,6 +173,7 @@
std::vector<std::unique_ptr<Plot> > plots_;
};
+} // namespace plotting
} // namespace webrtc
#endif // RTC_TOOLS_EVENT_LOG_VISUALIZER_PLOT_BASE_H_
diff --git a/rtc_tools/event_log_visualizer/plot_protobuf.cc b/rtc_tools/event_log_visualizer/plot_protobuf.cc
index e986a74..e5e0a8b 100644
--- a/rtc_tools/event_log_visualizer/plot_protobuf.cc
+++ b/rtc_tools/event_log_visualizer/plot_protobuf.cc
@@ -13,6 +13,7 @@
#include <memory>
namespace webrtc {
+namespace plotting {
ProtobufPlot::ProtobufPlot() {}
@@ -82,4 +83,5 @@
return plot;
}
+} // namespace plotting
} // namespace webrtc
diff --git a/rtc_tools/event_log_visualizer/plot_protobuf.h b/rtc_tools/event_log_visualizer/plot_protobuf.h
index f59d303..5c5cce1 100644
--- a/rtc_tools/event_log_visualizer/plot_protobuf.h
+++ b/rtc_tools/event_log_visualizer/plot_protobuf.h
@@ -17,6 +17,7 @@
#include "rtc_tools/event_log_visualizer/plot_base.h"
namespace webrtc {
+namespace plotting {
class ProtobufPlot final : public Plot {
public:
@@ -35,6 +36,7 @@
void ExportProtobuf(webrtc::analytics::ChartCollection* collection);
};
+} // namespace plotting
} // namespace webrtc
#endif // RTC_TOOLS_EVENT_LOG_VISUALIZER_PLOT_PROTOBUF_H_
diff --git a/rtc_tools/event_log_visualizer/plot_python.cc b/rtc_tools/event_log_visualizer/plot_python.cc
index 37c4d84..8f406e2 100644
--- a/rtc_tools/event_log_visualizer/plot_python.cc
+++ b/rtc_tools/event_log_visualizer/plot_python.cc
@@ -17,6 +17,7 @@
#include "rtc_base/checks.h"
namespace webrtc {
+namespace plotting {
PythonPlot::PythonPlot() {}
@@ -179,4 +180,5 @@
return plot;
}
+} // namespace plotting
} // namespace webrtc
diff --git a/rtc_tools/event_log_visualizer/plot_python.h b/rtc_tools/event_log_visualizer/plot_python.h
index 61d17a0..2a5a66c 100644
--- a/rtc_tools/event_log_visualizer/plot_python.h
+++ b/rtc_tools/event_log_visualizer/plot_python.h
@@ -13,6 +13,7 @@
#include "rtc_tools/event_log_visualizer/plot_base.h"
namespace webrtc {
+namespace plotting {
class PythonPlot final : public Plot {
public:
@@ -29,6 +30,7 @@
Plot* AppendNewPlot() override;
};
+} // namespace plotting
} // namespace webrtc
#endif // RTC_TOOLS_EVENT_LOG_VISUALIZER_PLOT_PYTHON_H_
diff --git a/rtc_tools/event_log_visualizer/triage_notifications.h b/rtc_tools/event_log_visualizer/triage_notifications.h
index 49e0620..641e2ae 100644
--- a/rtc_tools/event_log_visualizer/triage_notifications.h
+++ b/rtc_tools/event_log_visualizer/triage_notifications.h
@@ -14,136 +14,130 @@
#include <string>
namespace webrtc {
+namespace plotting {
-class IncomingRtpReceiveTimeGap {
+class TriageNotification {
+ public:
+ TriageNotification() : time_seconds_() {}
+ explicit TriageNotification(float time_seconds)
+ : time_seconds_(time_seconds) {}
+ virtual ~TriageNotification() = default;
+ virtual std::string ToString() = 0;
+ rtc::Optional<float> Time() { return time_seconds_; }
+
+ private:
+ rtc::Optional<float> time_seconds_;
+};
+
+class IncomingRtpReceiveTimeGap : public TriageNotification {
public:
IncomingRtpReceiveTimeGap(float time_seconds, int64_t duration)
- : time_seconds_(time_seconds), duration_(duration) {}
- float Time() const { return time_seconds_; }
- std::string ToString() const {
+ : TriageNotification(time_seconds), duration_(duration) {}
+ std::string ToString() {
return std::string("No RTP packets received for ") +
std::to_string(duration_) + std::string(" ms");
}
private:
- float time_seconds_;
int64_t duration_;
};
-class IncomingRtcpReceiveTimeGap {
+class IncomingRtcpReceiveTimeGap : public TriageNotification {
public:
IncomingRtcpReceiveTimeGap(float time_seconds, int64_t duration)
- : time_seconds_(time_seconds), duration_(duration) {}
- float Time() const { return time_seconds_; }
- std::string ToString() const {
+ : TriageNotification(time_seconds), duration_(duration) {}
+ std::string ToString() {
return std::string("No RTCP packets received for ") +
std::to_string(duration_) + std::string(" ms");
}
private:
- float time_seconds_;
int64_t duration_;
};
-class OutgoingRtpSendTimeGap {
+class OutgoingRtpSendTimeGap : public TriageNotification {
public:
OutgoingRtpSendTimeGap(float time_seconds, int64_t duration)
- : time_seconds_(time_seconds), duration_(duration) {}
- float Time() const { return time_seconds_; }
- std::string ToString() const {
+ : TriageNotification(time_seconds), duration_(duration) {}
+ std::string ToString() {
return std::string("No RTP packets sent for ") + std::to_string(duration_) +
std::string(" ms");
}
private:
- float time_seconds_;
int64_t duration_;
};
-class OutgoingRtcpSendTimeGap {
+class OutgoingRtcpSendTimeGap : public TriageNotification {
public:
OutgoingRtcpSendTimeGap(float time_seconds, int64_t duration)
- : time_seconds_(time_seconds), duration_(duration) {}
- float Time() const { return time_seconds_; }
- std::string ToString() const {
+ : TriageNotification(time_seconds), duration_(duration) {}
+ std::string ToString() {
return std::string("No RTCP packets sent for ") +
std::to_string(duration_) + std::string(" ms");
}
private:
- float time_seconds_;
int64_t duration_;
};
-class IncomingSeqNumJump {
+class IncomingSeqNoJump : public TriageNotification {
public:
- IncomingSeqNumJump(float time_seconds, uint32_t ssrc)
- : time_seconds_(time_seconds), ssrc_(ssrc) {}
- float Time() const { return time_seconds_; }
- std::string ToString() const {
+ IncomingSeqNoJump(float time_seconds, uint32_t ssrc)
+ : TriageNotification(time_seconds), ssrc_(ssrc) {}
+ std::string ToString() {
return std::string("Sequence number jumps on incoming SSRC ") +
std::to_string(ssrc_);
}
private:
- float time_seconds_;
-
uint32_t ssrc_;
};
-class IncomingCaptureTimeJump {
+class IncomingCaptureTimeJump : public TriageNotification {
public:
IncomingCaptureTimeJump(float time_seconds, uint32_t ssrc)
- : time_seconds_(time_seconds), ssrc_(ssrc) {}
- float Time() const { return time_seconds_; }
- std::string ToString() const {
+ : TriageNotification(time_seconds), ssrc_(ssrc) {}
+ std::string ToString() {
return std::string("Capture timestamp jumps on incoming SSRC ") +
std::to_string(ssrc_);
}
private:
- float time_seconds_;
-
uint32_t ssrc_;
};
-class OutgoingSeqNoJump {
+class OutgoingSeqNoJump : public TriageNotification {
public:
OutgoingSeqNoJump(float time_seconds, uint32_t ssrc)
- : time_seconds_(time_seconds), ssrc_(ssrc) {}
- float Time() const { return time_seconds_; }
- std::string ToString() const {
+ : TriageNotification(time_seconds), ssrc_(ssrc) {}
+ std::string ToString() {
return std::string("Sequence number jumps on outgoing SSRC ") +
std::to_string(ssrc_);
}
private:
- float time_seconds_;
-
uint32_t ssrc_;
};
-class OutgoingCaptureTimeJump {
+class OutgoingCaptureTimeJump : public TriageNotification {
public:
OutgoingCaptureTimeJump(float time_seconds, uint32_t ssrc)
- : time_seconds_(time_seconds), ssrc_(ssrc) {}
- float Time() const { return time_seconds_; }
- std::string ToString() const {
+ : TriageNotification(time_seconds), ssrc_(ssrc) {}
+ std::string ToString() {
return std::string("Capture timestamp jumps on outgoing SSRC ") +
std::to_string(ssrc_);
}
private:
- float time_seconds_;
-
uint32_t ssrc_;
};
-class OutgoingHighLoss {
+class OutgoingHighLoss : public TriageNotification {
public:
explicit OutgoingHighLoss(double avg_loss_fraction)
: avg_loss_fraction_(avg_loss_fraction) {}
- std::string ToString() const {
+ std::string ToString() {
return std::string("High average loss (") +
std::to_string(avg_loss_fraction_ * 100) +
std::string("%) across the call.");
@@ -153,6 +147,7 @@
double avg_loss_fraction_;
};
+} // namespace plotting
} // namespace webrtc
#endif // RTC_TOOLS_EVENT_LOG_VISUALIZER_TRIAGE_NOTIFICATIONS_H_