Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2136)

Unified Diff: webrtc/tools/event_log_visualizer/analyzer.cc

Issue 2234883002: Adds function for computing moving average to visualization tool. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Comments from Stefan Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « webrtc/tools/event_log_visualizer/analyzer.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: webrtc/tools/event_log_visualizer/analyzer.cc
diff --git a/webrtc/tools/event_log_visualizer/analyzer.cc b/webrtc/tools/event_log_visualizer/analyzer.cc
index 1db7672b9cb01451ffc4d0b54293eede97c82463..60051a775e2051f4da5ec134f5dfc55df62b6c35 100644
--- a/webrtc/tools/event_log_visualizer/analyzer.cc
+++ b/webrtc/tools/event_log_visualizer/analyzer.cc
@@ -80,6 +80,12 @@ int64_t WrappingDifference(uint32_t later, uint32_t earlier, int64_t modulus) {
if (difference < min_difference) {
difference += modulus;
}
+ if (difference > max_difference / 2 || difference < min_difference / 2) {
+ LOG(LS_WARNING) << "Difference between" << later << " and " << earlier
+ << " expected to be in the range (" << min_difference / 2
+ << "," << max_difference / 2 << ") but is " << difference
+ << ". Correct unwrapping is uncertain.";
+ }
return difference;
}
@@ -98,6 +104,26 @@ constexpr float kRightMargin = 0.02f;
constexpr float kBottomMargin = 0.02f;
constexpr float kTopMargin = 0.05f;
+class PacketSizeBytes {
+ public:
+ using DataType = LoggedRtpPacket;
+ using ResultType = size_t;
+ size_t operator()(const LoggedRtpPacket& packet) {
+ return packet.total_length;
+ }
+};
+
+class SequenceNumberDiff {
+ public:
+ using DataType = LoggedRtpPacket;
+ using ResultType = int64_t;
+ int64_t operator()(const LoggedRtpPacket& old_packet,
+ const LoggedRtpPacket& new_packet) {
+ return WrappingDifference(new_packet.header.sequenceNumber,
+ old_packet.header.sequenceNumber, 1ul << 16);
+ }
+};
+
class NetworkDelayDiff {
public:
class AbsSendTime {
@@ -140,6 +166,19 @@ class NetworkDelayDiff {
double delay_change =
static_cast<double>(recv_time_diff) / 1000 -
static_cast<double>(send_time_diff) / kVideoSampleRate * 1000;
+ if (delay_change < -10000 || 10000 < delay_change) {
+ LOG(LS_WARNING) << "Very large delay change. Timestamps correct?";
+ LOG(LS_WARNING) << "Old capture time " << old_packet.header.timestamp
+ << ", received time " << old_packet.timestamp;
+ LOG(LS_WARNING) << "New capture time " << new_packet.header.timestamp
+ << ", received time " << new_packet.timestamp;
+ LOG(LS_WARNING) << "Receive time difference " << recv_time_diff << " = "
+ << static_cast<double>(recv_time_diff) / 1000000 << "s";
+ LOG(LS_WARNING) << "Send time difference " << send_time_diff << " = "
+ << static_cast<double>(send_time_diff) /
+ kVideoSampleRate
+ << "s";
+ }
return delay_change;
}
};
@@ -161,6 +200,23 @@ class Accumulated {
ResultType sum = 0;
};
+// For each element in data, use |Extractor| to extract a y-coordinate and
+// store the result in a TimeSeries.
+template <typename Extractor>
+void Pointwise(const std::vector<typename Extractor::DataType>& data,
+ uint64_t begin_time,
+ TimeSeries* result) {
+ Extractor extract;
+ for (size_t i = 0; i < data.size(); i++) {
+ float x = static_cast<float>(data[i].timestamp - begin_time) / 1000000;
+ float y = extract(data[i]);
+ result->points.emplace_back(x, y);
+ }
+}
+
+// For each pair of adjacent elements in |data|, use |Extractor| 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 Extractor>
void Pairwise(const std::vector<typename Extractor::DataType>& data,
uint64_t begin_time,
@@ -173,6 +229,41 @@ void Pairwise(const std::vector<typename Extractor::DataType>& data,
}
}
+// Calculates a moving average of |data| and stores the result in a TimeSeries.
+// 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 Extractor>
+void MovingAverage(const std::vector<typename Extractor::DataType>& data,
+ uint64_t begin_time,
+ uint64_t end_time,
+ uint64_t window_duration_us,
+ uint64_t step,
+ float y_scaling,
+ webrtc::plotting::TimeSeries* result) {
+ size_t window_index_begin = 0;
+ size_t window_index_end = 0;
+ typename Extractor::ResultType sum_in_window = 0;
+ Extractor extract;
+
+ for (uint64_t t = begin_time; t < end_time + step; t += step) {
+ while (window_index_end < data.size() &&
+ data[window_index_end].timestamp < t) {
+ sum_in_window += extract(data[window_index_end]);
+ ++window_index_end;
+ }
+ while (window_index_begin < data.size() &&
+ data[window_index_begin].timestamp < t - window_duration_us) {
+ sum_in_window -= extract(data[window_index_begin]);
+ ++window_index_begin;
+ }
+ float window_duration_s = static_cast<float>(window_duration_us) / 1000000;
+ float x = static_cast<float>(t - begin_time) / 1000000;
+ float y = sum_in_window / window_duration_s * y_scaling;
+ result->points.emplace_back(x, y);
+ }
+}
+
} // namespace
EventLogAnalyzer::EventLogAnalyzer(const ParsedRtcEventLog& log)
@@ -381,40 +472,20 @@ bool EventLogAnalyzer::IsAudioSsrc(StreamId stream_id) {
void EventLogAnalyzer::CreatePacketGraph(PacketDirection desired_direction,
Plot* plot) {
- std::map<uint32_t, TimeSeries> time_series;
-
- PacketDirection direction;
- MediaType media_type;
- uint8_t header[IP_PACKET_SIZE];
- size_t header_length, total_length;
-
- 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, &media_type, header,
- &header_length, &total_length);
- if (direction == desired_direction) {
- // Parse header to get SSRC.
- RtpUtility::RtpHeaderParser rtp_parser(header, header_length);
- RTPHeader parsed_header;
- rtp_parser.Parse(&parsed_header);
- // Filter on SSRC.
- if (MatchingSsrc(parsed_header.ssrc, desired_ssrc_)) {
- uint64_t timestamp = parsed_log_.GetTimestamp(i);
- float x = static_cast<float>(timestamp - begin_time_) / 1000000;
- float y = total_length;
- time_series[parsed_header.ssrc].points.push_back(
- TimeSeriesPoint(x, y));
- }
- }
+ 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;
}
- }
- // Set labels and put in graph.
- for (auto& kv : time_series) {
- kv.second.label = SsrcToString(kv.first);
- kv.second.style = BAR_GRAPH;
- plot->series_list_.push_back(std::move(kv.second));
+ TimeSeries time_series;
+ time_series.label = SsrcToString(stream_id.GetSsrc());
+ time_series.style = BAR_GRAPH;
+ Pointwise<PacketSizeBytes>(packet_stream, begin_time_, &time_series);
+ plot->series_list_.push_back(std::move(time_series));
}
plot->SetXAxis(0, call_duration_s_, "Time (s)", kLeftMargin, kRightMargin);
@@ -468,48 +539,20 @@ void EventLogAnalyzer::CreatePlayoutGraph(Plot* plot) {
// For each SSRC, plot the time between the consecutive playouts.
void EventLogAnalyzer::CreateSequenceNumberGraph(Plot* plot) {
- std::map<uint32_t, TimeSeries> time_series;
- std::map<uint32_t, uint16_t> last_seqno;
-
- PacketDirection direction;
- MediaType media_type;
- uint8_t header[IP_PACKET_SIZE];
- size_t header_length, total_length;
-
- 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, &media_type, header,
- &header_length, &total_length);
- uint64_t timestamp = parsed_log_.GetTimestamp(i);
- if (direction == PacketDirection::kIncomingPacket) {
- // Parse header to get SSRC.
- RtpUtility::RtpHeaderParser rtp_parser(header, header_length);
- RTPHeader parsed_header;
- rtp_parser.Parse(&parsed_header);
- // Filter on SSRC.
- if (MatchingSsrc(parsed_header.ssrc, desired_ssrc_)) {
- float x = static_cast<float>(timestamp - begin_time_) / 1000000;
- int y = WrappingDifference(parsed_header.sequenceNumber,
- last_seqno[parsed_header.ssrc], 1ul << 16);
- if (time_series[parsed_header.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[parsed_header.ssrc].points.push_back(
- TimeSeriesPoint(x, y));
- last_seqno[parsed_header.ssrc] = parsed_header.sequenceNumber;
- }
- }
+ 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;
}
- }
- // Set labels and put in graph.
- for (auto& kv : time_series) {
- kv.second.label = SsrcToString(kv.first);
- kv.second.style = BAR_GRAPH;
- plot->series_list_.push_back(std::move(kv.second));
+ TimeSeries time_series;
+ time_series.label = SsrcToString(stream_id.GetSsrc());
+ time_series.style = BAR_GRAPH;
+ Pairwise<SequenceNumberDiff>(packet_stream, begin_time_, &time_series);
+ plot->series_list_.push_back(std::move(time_series));
}
plot->SetXAxis(0, call_duration_s_, "Time (s)", kLeftMargin, kRightMargin);
@@ -638,13 +681,13 @@ void EventLogAnalyzer::CreateTotalBitrateGraph(
while (window_index_end < packets.size() &&
packets[window_index_end].timestamp < time) {
bytes_in_window += packets[window_index_end].size;
- window_index_end++;
+ ++window_index_end;
}
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++;
+ ++window_index_begin;
}
float window_duration_in_seconds =
static_cast<float>(window_duration_) / 1000000;
@@ -687,69 +730,23 @@ void EventLogAnalyzer::CreateTotalBitrateGraph(
void EventLogAnalyzer::CreateStreamBitrateGraph(
PacketDirection desired_direction,
Plot* plot) {
- struct TimestampSize {
- TimestampSize(uint64_t t, size_t s) : timestamp(t), size(s) {}
- uint64_t timestamp;
- size_t size;
- };
- std::map<uint32_t, std::vector<TimestampSize>> packets;
-
- PacketDirection direction;
- MediaType media_type;
- uint8_t header[IP_PACKET_SIZE];
- size_t header_length, 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, &media_type, header,
- &header_length, &total_length);
- if (direction == desired_direction) {
- // Parse header to get SSRC.
- RtpUtility::RtpHeaderParser rtp_parser(header, header_length);
- RTPHeader parsed_header;
- rtp_parser.Parse(&parsed_header);
- // Filter on SSRC.
- if (MatchingSsrc(parsed_header.ssrc, desired_ssrc_)) {
- uint64_t timestamp = parsed_log_.GetTimestamp(i);
- packets[parsed_header.ssrc].push_back(
- TimestampSize(timestamp, total_length));
- }
- }
- }
- }
-
- for (auto& kv : packets) {
- 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.
- plot->series_list_.push_back(TimeSeries());
- for (uint64_t time = begin_time_; time < end_time_ + step_; time += step_) {
- while (window_index_end < kv.second.size() &&
- kv.second[window_index_end].timestamp < time) {
- bytes_in_window += kv.second[window_index_end].size;
- window_index_end++;
- }
- while (window_index_begin < kv.second.size() &&
- kv.second[window_index_begin].timestamp <
- time - window_duration_) {
- RTC_DCHECK_LE(kv.second[window_index_begin].size, bytes_in_window);
- bytes_in_window -= kv.second[window_index_begin].size;
- window_index_begin++;
- }
- float window_duration_in_seconds =
- static_cast<float>(window_duration_) / 1000000;
- float x = static_cast<float>(time - begin_time_) / 1000000;
- float y = bytes_in_window * 8 / window_duration_in_seconds / 1000;
- plot->series_list_.back().points.push_back(TimeSeriesPoint(x, y));
+ 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;
}
- // Set labels.
- plot->series_list_.back().label = SsrcToString(kv.first);
- plot->series_list_.back().style = LINE_GRAPH;
+ TimeSeries time_series;
+ time_series.label = SsrcToString(stream_id.GetSsrc());
+ time_series.style = LINE_GRAPH;
+ double bytes_to_kilobits = 8.0 / 1000;
+ MovingAverage<PacketSizeBytes>(packet_stream, begin_time_, end_time_,
+ window_duration_, step_, bytes_to_kilobits,
+ &time_series);
+ plot->series_list_.push_back(std::move(time_series));
}
plot->SetXAxis(0, call_duration_s_, "Time (s)", kLeftMargin, kRightMargin);
« no previous file with comments | « webrtc/tools/event_log_visualizer/analyzer.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698