Visualize delay changes based on both abs-send-time and capture time.
Adds reusable template function objects to extract interesting
statistics from data sets. A few more of these will be added later
to reduce the code size.
Review-Url: https://codereview.webrtc.org/2220383004
Cr-Commit-Position: refs/heads/master@{#13713}
diff --git a/webrtc/tools/event_log_visualizer/analyzer.cc b/webrtc/tools/event_log_visualizer/analyzer.cc
index 1f7973e..42115e8 100644
--- a/webrtc/tools/event_log_visualizer/analyzer.cc
+++ b/webrtc/tools/event_log_visualizer/analyzer.cc
@@ -57,7 +57,7 @@
// and 18 bits for fractions of a second. Thus, we divide by 2^18 to get the
// time in seconds and then multiply by 1000000 to convert to microseconds.
static constexpr double kTimestampToMicroSec =
- 1000000.0 / static_cast<double>(1 << 18);
+ 1000000.0 / static_cast<double>(1ul << 18);
return abs_send_time * kTimestampToMicroSec;
}
@@ -98,6 +98,81 @@
constexpr float kBottomMargin = 0.02f;
constexpr float kTopMargin = 0.05f;
+class NetworkDelayDiff {
+ public:
+ class AbsSendTime {
+ public:
+ using DataType = LoggedRtpPacket;
+ using ResultType = double;
+ double operator()(const LoggedRtpPacket& old_packet,
+ const LoggedRtpPacket& new_packet) {
+ if (old_packet.header.extension.hasAbsoluteSendTime &&
+ new_packet.header.extension.hasAbsoluteSendTime) {
+ 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.timestamp - old_packet.timestamp;
+ return static_cast<double>(recv_time_diff -
+ AbsSendTimeToMicroseconds(send_time_diff)) /
+ 1000;
+ } else {
+ return 0;
+ }
+ }
+ };
+
+ class CaptureTime {
+ public:
+ using DataType = LoggedRtpPacket;
+ using ResultType = double;
+ double operator()(const LoggedRtpPacket& old_packet,
+ 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.timestamp - old_packet.timestamp;
+
+ const double kVideoSampleRate = 90000;
+ // TODO(terelius): We treat all streams as video for now, even though
+ // audio might be sampled at e.g. 16kHz, because it is really difficult to
+ // figure out the true sampling rate of a stream. The effect is that the
+ // delay will be scaled incorrectly for non-video streams.
+
+ double delay_change =
+ static_cast<double>(recv_time_diff) / 1000 -
+ static_cast<double>(send_time_diff) / kVideoSampleRate * 1000;
+ return delay_change;
+ }
+ };
+};
+
+template <typename Extractor>
+class Accumulated {
+ public:
+ using DataType = typename Extractor::DataType;
+ using ResultType = typename Extractor::ResultType;
+ ResultType operator()(const DataType& old_packet,
+ const DataType& new_packet) {
+ sum += extract(old_packet, new_packet);
+ return sum;
+ }
+
+ private:
+ Extractor extract;
+ ResultType sum = 0;
+};
+
+template <typename Extractor>
+void Pairwise(const std::vector<typename Extractor::DataType>& data,
+ uint64_t begin_time,
+ TimeSeries* result) {
+ Extractor extract;
+ for (size_t i = 1; i < data.size(); i++) {
+ float x = static_cast<float>(data[i].timestamp - begin_time) / 1000000;
+ float y = extract(data[i - 1], data[i]);
+ result->points.emplace_back(x, y);
+ }
+}
+
} // namespace
EventLogAnalyzer::EventLogAnalyzer(const ParsedRtcEventLog& log)
@@ -446,43 +521,28 @@
void EventLogAnalyzer::CreateDelayChangeGraph(Plot* plot) {
for (auto& kv : rtp_packets_) {
StreamId stream_id = kv.first;
+ const std::vector<LoggedRtpPacket>& packet_stream = kv.second;
+ uint32_t ssrc = stream_id.GetSsrc();
// Filter on direction and SSRC.
if (stream_id.GetDirection() != kIncomingPacket ||
- !MatchingSsrc(stream_id.GetSsrc(), desired_ssrc_)) {
+ !MatchingSsrc(ssrc, desired_ssrc_) || IsAudioSsrc(stream_id) ||
+ !IsVideoSsrc(stream_id) || IsRtxSsrc(stream_id)) {
continue;
}
- TimeSeries time_series;
- time_series.label = SsrcToString(stream_id.GetSsrc());
- time_series.style = BAR_GRAPH;
- const std::vector<LoggedRtpPacket>& packet_stream = kv.second;
- int64_t last_abs_send_time = 0;
- int64_t last_timestamp = 0;
- for (const LoggedRtpPacket& packet : packet_stream) {
- if (packet.header.extension.hasAbsoluteSendTime) {
- int64_t send_time_diff =
- WrappingDifference(packet.header.extension.absoluteSendTime,
- last_abs_send_time, 1ul << 24);
- int64_t recv_time_diff = packet.timestamp - last_timestamp;
+ TimeSeries capture_time_data;
+ capture_time_data.label = SsrcToString(ssrc) + " capture-time";
+ capture_time_data.style = BAR_GRAPH;
+ Pairwise<NetworkDelayDiff::CaptureTime>(packet_stream, begin_time_,
+ &capture_time_data);
+ plot->series_list_.push_back(std::move(capture_time_data));
- last_abs_send_time = packet.header.extension.absoluteSendTime;
- last_timestamp = packet.timestamp;
-
- float x = static_cast<float>(packet.timestamp - begin_time_) / 1000000;
- double y =
- static_cast<double>(recv_time_diff -
- AbsSendTimeToMicroseconds(send_time_diff)) /
- 1000;
- if (time_series.points.size() == 0) {
- // There were no previously logged packets for this SSRC.
- // Generate a point, but place it on the x-axis.
- y = 0;
- }
- time_series.points.emplace_back(x, y);
- }
- }
- // Add the data set to the plot.
- plot->series_list_.push_back(std::move(time_series));
+ TimeSeries send_time_data;
+ send_time_data.label = SsrcToString(ssrc) + " abs-send-time";
+ send_time_data.style = BAR_GRAPH;
+ Pairwise<NetworkDelayDiff::AbsSendTime>(packet_stream, begin_time_,
+ &send_time_data);
+ plot->series_list_.push_back(std::move(send_time_data));
}
plot->SetXAxis(0, call_duration_s_, "Time (s)", kLeftMargin, kRightMargin);
@@ -494,43 +554,28 @@
void EventLogAnalyzer::CreateAccumulatedDelayChangeGraph(Plot* plot) {
for (auto& kv : rtp_packets_) {
StreamId stream_id = kv.first;
+ const std::vector<LoggedRtpPacket>& packet_stream = kv.second;
+ uint32_t ssrc = stream_id.GetSsrc();
// Filter on direction and SSRC.
if (stream_id.GetDirection() != kIncomingPacket ||
- !MatchingSsrc(stream_id.GetSsrc(), desired_ssrc_)) {
+ !MatchingSsrc(ssrc, desired_ssrc_) || IsAudioSsrc(stream_id) ||
+ !IsVideoSsrc(stream_id) || IsRtxSsrc(stream_id)) {
continue;
}
- TimeSeries time_series;
- time_series.label = SsrcToString(stream_id.GetSsrc());
- time_series.style = LINE_GRAPH;
- const std::vector<LoggedRtpPacket>& packet_stream = kv.second;
- int64_t last_abs_send_time = 0;
- int64_t last_timestamp = 0;
- double accumulated_delay_ms = 0;
- for (const LoggedRtpPacket& packet : packet_stream) {
- if (packet.header.extension.hasAbsoluteSendTime) {
- int64_t send_time_diff =
- WrappingDifference(packet.header.extension.absoluteSendTime,
- last_abs_send_time, 1ul << 24);
- int64_t recv_time_diff = packet.timestamp - last_timestamp;
- last_abs_send_time = packet.header.extension.absoluteSendTime;
- last_timestamp = packet.timestamp;
+ TimeSeries capture_time_data;
+ capture_time_data.label = SsrcToString(ssrc) + " capture-time";
+ capture_time_data.style = LINE_GRAPH;
+ Pairwise<Accumulated<NetworkDelayDiff::CaptureTime>>(
+ packet_stream, begin_time_, &capture_time_data);
+ plot->series_list_.push_back(std::move(capture_time_data));
- float x = static_cast<float>(packet.timestamp - begin_time_) / 1000000;
- accumulated_delay_ms +=
- static_cast<double>(recv_time_diff -
- AbsSendTimeToMicroseconds(send_time_diff)) /
- 1000;
- if (time_series.points.size() == 0) {
- // There were no previously logged packets for this SSRC.
- // Generate a point, but place it on the x-axis.
- accumulated_delay_ms = 0;
- }
- time_series.points.emplace_back(x, accumulated_delay_ms);
- }
- }
- // Add the data set to the plot.
- plot->series_list_.push_back(std::move(time_series));
+ TimeSeries send_time_data;
+ send_time_data.label = SsrcToString(ssrc) + " abs-send-time";
+ send_time_data.style = LINE_GRAPH;
+ Pairwise<Accumulated<NetworkDelayDiff::AbsSendTime>>(
+ packet_stream, begin_time_, &send_time_data);
+ plot->series_list_.push_back(std::move(send_time_data));
}
plot->SetXAxis(0, call_duration_s_, "Time (s)", kLeftMargin, kRightMargin);
diff --git a/webrtc/tools/event_log_visualizer/analyzer.h b/webrtc/tools/event_log_visualizer/analyzer.h
index ce2179f..4a1a2d6 100644
--- a/webrtc/tools/event_log_visualizer/analyzer.h
+++ b/webrtc/tools/event_log_visualizer/analyzer.h
@@ -25,6 +25,31 @@
namespace webrtc {
namespace plotting {
+struct LoggedRtpPacket {
+ LoggedRtpPacket(uint64_t timestamp, RTPHeader header, size_t total_length)
+ : timestamp(timestamp), header(header), total_length(total_length) {}
+ uint64_t timestamp;
+ RTPHeader header;
+ 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 BwePacketLossEvent {
+ uint64_t timestamp;
+ int32_t new_bitrate;
+ uint8_t fraction_loss;
+ int32_t expected_packets;
+};
+
class EventLogAnalyzer {
public:
// The EventLogAnalyzer keeps a reference to the ParsedRtcEventLog for the
@@ -73,33 +98,6 @@
webrtc::PacketDirection direction_;
};
- struct LoggedRtpPacket {
- LoggedRtpPacket(uint64_t timestamp, RTPHeader header, size_t total_length)
- : timestamp(timestamp), header(header), total_length(total_length) {}
- uint64_t timestamp;
- RTPHeader header;
- 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 BwePacketLossEvent {
- uint64_t timestamp;
- int32_t new_bitrate;
- uint8_t fraction_loss;
- int32_t expected_packets;
- };
-
bool IsRtxSsrc(StreamId stream_id);
bool IsVideoSsrc(StreamId stream_id);