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

Side by Side 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 unified diff | Download patch
« no previous file with comments | « webrtc/tools/event_log_visualizer/analyzer.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. 2 * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license 4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source 5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found 6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may 7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree. 8 * be found in the AUTHORS file in the root of the source tree.
9 */ 9 */
10 10
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
73 int64_t difference = 73 int64_t difference =
74 static_cast<int64_t>(later) - static_cast<int64_t>(earlier); 74 static_cast<int64_t>(later) - static_cast<int64_t>(earlier);
75 int64_t max_difference = modulus / 2; 75 int64_t max_difference = modulus / 2;
76 int64_t min_difference = max_difference - modulus + 1; 76 int64_t min_difference = max_difference - modulus + 1;
77 if (difference > max_difference) { 77 if (difference > max_difference) {
78 difference -= modulus; 78 difference -= modulus;
79 } 79 }
80 if (difference < min_difference) { 80 if (difference < min_difference) {
81 difference += modulus; 81 difference += modulus;
82 } 82 }
83 if (difference > max_difference / 2 || difference < min_difference / 2) {
84 LOG(LS_WARNING) << "Difference between" << later << " and " << earlier
85 << " expected to be in the range (" << min_difference / 2
86 << "," << max_difference / 2 << ") but is " << difference
87 << ". Correct unwrapping is uncertain.";
88 }
83 return difference; 89 return difference;
84 } 90 }
85 91
86 void RegisterHeaderExtensions( 92 void RegisterHeaderExtensions(
87 const std::vector<webrtc::RtpExtension>& extensions, 93 const std::vector<webrtc::RtpExtension>& extensions,
88 webrtc::RtpHeaderExtensionMap* extension_map) { 94 webrtc::RtpHeaderExtensionMap* extension_map) {
89 extension_map->Erase(); 95 extension_map->Erase();
90 for (const webrtc::RtpExtension& extension : extensions) { 96 for (const webrtc::RtpExtension& extension : extensions) {
91 extension_map->Register(webrtc::StringToRtpExtensionType(extension.uri), 97 extension_map->Register(webrtc::StringToRtpExtensionType(extension.uri),
92 extension.id); 98 extension.id);
93 } 99 }
94 } 100 }
95 101
96 constexpr float kLeftMargin = 0.01f; 102 constexpr float kLeftMargin = 0.01f;
97 constexpr float kRightMargin = 0.02f; 103 constexpr float kRightMargin = 0.02f;
98 constexpr float kBottomMargin = 0.02f; 104 constexpr float kBottomMargin = 0.02f;
99 constexpr float kTopMargin = 0.05f; 105 constexpr float kTopMargin = 0.05f;
100 106
107 class PacketSizeBytes {
108 public:
109 using DataType = LoggedRtpPacket;
110 using ResultType = size_t;
111 size_t operator()(const LoggedRtpPacket& packet) {
112 return packet.total_length;
113 }
114 };
115
116 class SequenceNumberDiff {
117 public:
118 using DataType = LoggedRtpPacket;
119 using ResultType = int64_t;
120 int64_t operator()(const LoggedRtpPacket& old_packet,
121 const LoggedRtpPacket& new_packet) {
122 return WrappingDifference(new_packet.header.sequenceNumber,
123 old_packet.header.sequenceNumber, 1ul << 16);
124 }
125 };
126
101 class NetworkDelayDiff { 127 class NetworkDelayDiff {
102 public: 128 public:
103 class AbsSendTime { 129 class AbsSendTime {
104 public: 130 public:
105 using DataType = LoggedRtpPacket; 131 using DataType = LoggedRtpPacket;
106 using ResultType = double; 132 using ResultType = double;
107 double operator()(const LoggedRtpPacket& old_packet, 133 double operator()(const LoggedRtpPacket& old_packet,
108 const LoggedRtpPacket& new_packet) { 134 const LoggedRtpPacket& new_packet) {
109 if (old_packet.header.extension.hasAbsoluteSendTime && 135 if (old_packet.header.extension.hasAbsoluteSendTime &&
110 new_packet.header.extension.hasAbsoluteSendTime) { 136 new_packet.header.extension.hasAbsoluteSendTime) {
(...skipping 22 matching lines...) Expand all
133 159
134 const double kVideoSampleRate = 90000; 160 const double kVideoSampleRate = 90000;
135 // TODO(terelius): We treat all streams as video for now, even though 161 // TODO(terelius): We treat all streams as video for now, even though
136 // audio might be sampled at e.g. 16kHz, because it is really difficult to 162 // audio might be sampled at e.g. 16kHz, because it is really difficult to
137 // figure out the true sampling rate of a stream. The effect is that the 163 // figure out the true sampling rate of a stream. The effect is that the
138 // delay will be scaled incorrectly for non-video streams. 164 // delay will be scaled incorrectly for non-video streams.
139 165
140 double delay_change = 166 double delay_change =
141 static_cast<double>(recv_time_diff) / 1000 - 167 static_cast<double>(recv_time_diff) / 1000 -
142 static_cast<double>(send_time_diff) / kVideoSampleRate * 1000; 168 static_cast<double>(send_time_diff) / kVideoSampleRate * 1000;
169 if (delay_change < -10000 || 10000 < delay_change) {
170 LOG(LS_WARNING) << "Very large delay change. Timestamps correct?";
171 LOG(LS_WARNING) << "Old capture time " << old_packet.header.timestamp
172 << ", received time " << old_packet.timestamp;
173 LOG(LS_WARNING) << "New capture time " << new_packet.header.timestamp
174 << ", received time " << new_packet.timestamp;
175 LOG(LS_WARNING) << "Receive time difference " << recv_time_diff << " = "
176 << static_cast<double>(recv_time_diff) / 1000000 << "s";
177 LOG(LS_WARNING) << "Send time difference " << send_time_diff << " = "
178 << static_cast<double>(send_time_diff) /
179 kVideoSampleRate
180 << "s";
181 }
143 return delay_change; 182 return delay_change;
144 } 183 }
145 }; 184 };
146 }; 185 };
147 186
148 template <typename Extractor> 187 template <typename Extractor>
149 class Accumulated { 188 class Accumulated {
150 public: 189 public:
151 using DataType = typename Extractor::DataType; 190 using DataType = typename Extractor::DataType;
152 using ResultType = typename Extractor::ResultType; 191 using ResultType = typename Extractor::ResultType;
153 ResultType operator()(const DataType& old_packet, 192 ResultType operator()(const DataType& old_packet,
154 const DataType& new_packet) { 193 const DataType& new_packet) {
155 sum += extract(old_packet, new_packet); 194 sum += extract(old_packet, new_packet);
156 return sum; 195 return sum;
157 } 196 }
158 197
159 private: 198 private:
160 Extractor extract; 199 Extractor extract;
161 ResultType sum = 0; 200 ResultType sum = 0;
162 }; 201 };
163 202
203 // For each element in data, use |Extractor| to extract a y-coordinate and
204 // store the result in a TimeSeries.
205 template <typename Extractor>
206 void Pointwise(const std::vector<typename Extractor::DataType>& data,
207 uint64_t begin_time,
208 TimeSeries* result) {
209 Extractor extract;
210 for (size_t i = 0; i < data.size(); i++) {
211 float x = static_cast<float>(data[i].timestamp - begin_time) / 1000000;
212 float y = extract(data[i]);
213 result->points.emplace_back(x, y);
214 }
215 }
216
217 // For each pair of adjacent elements in |data|, use |Extractor| to extract a
218 // y-coordinate and store the result in a TimeSeries. Note that the x-coordinate
219 // will be the time of the second element in the pair.
164 template <typename Extractor> 220 template <typename Extractor>
165 void Pairwise(const std::vector<typename Extractor::DataType>& data, 221 void Pairwise(const std::vector<typename Extractor::DataType>& data,
166 uint64_t begin_time, 222 uint64_t begin_time,
167 TimeSeries* result) { 223 TimeSeries* result) {
168 Extractor extract; 224 Extractor extract;
169 for (size_t i = 1; i < data.size(); i++) { 225 for (size_t i = 1; i < data.size(); i++) {
170 float x = static_cast<float>(data[i].timestamp - begin_time) / 1000000; 226 float x = static_cast<float>(data[i].timestamp - begin_time) / 1000000;
171 float y = extract(data[i - 1], data[i]); 227 float y = extract(data[i - 1], data[i]);
172 result->points.emplace_back(x, y); 228 result->points.emplace_back(x, y);
173 } 229 }
174 } 230 }
175 231
232 // Calculates a moving average of |data| and stores the result in a TimeSeries.
233 // A data point is generated every |step| microseconds from |begin_time|
234 // to |end_time|. The value of each data point is the average of the data
235 // during the preceeding |window_duration_us| microseconds.
236 template <typename Extractor>
237 void MovingAverage(const std::vector<typename Extractor::DataType>& data,
238 uint64_t begin_time,
239 uint64_t end_time,
240 uint64_t window_duration_us,
241 uint64_t step,
242 float y_scaling,
243 webrtc::plotting::TimeSeries* result) {
244 size_t window_index_begin = 0;
245 size_t window_index_end = 0;
246 typename Extractor::ResultType sum_in_window = 0;
247 Extractor extract;
248
249 for (uint64_t t = begin_time; t < end_time + step; t += step) {
250 while (window_index_end < data.size() &&
251 data[window_index_end].timestamp < t) {
252 sum_in_window += extract(data[window_index_end]);
253 ++window_index_end;
254 }
255 while (window_index_begin < data.size() &&
256 data[window_index_begin].timestamp < t - window_duration_us) {
257 sum_in_window -= extract(data[window_index_begin]);
258 ++window_index_begin;
259 }
260 float window_duration_s = static_cast<float>(window_duration_us) / 1000000;
261 float x = static_cast<float>(t - begin_time) / 1000000;
262 float y = sum_in_window / window_duration_s * y_scaling;
263 result->points.emplace_back(x, y);
264 }
265 }
266
176 } // namespace 267 } // namespace
177 268
178 EventLogAnalyzer::EventLogAnalyzer(const ParsedRtcEventLog& log) 269 EventLogAnalyzer::EventLogAnalyzer(const ParsedRtcEventLog& log)
179 : parsed_log_(log), window_duration_(250000), step_(10000) { 270 : parsed_log_(log), window_duration_(250000), step_(10000) {
180 uint64_t first_timestamp = std::numeric_limits<uint64_t>::max(); 271 uint64_t first_timestamp = std::numeric_limits<uint64_t>::max();
181 uint64_t last_timestamp = std::numeric_limits<uint64_t>::min(); 272 uint64_t last_timestamp = std::numeric_limits<uint64_t>::min();
182 273
183 // Maps a stream identifier consisting of ssrc and direction 274 // Maps a stream identifier consisting of ssrc and direction
184 // to the header extensions used by that stream, 275 // to the header extensions used by that stream,
185 std::map<StreamId, RtpHeaderExtensionMap> extension_maps; 276 std::map<StreamId, RtpHeaderExtensionMap> extension_maps;
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after
374 bool EventLogAnalyzer::IsVideoSsrc(StreamId stream_id) { 465 bool EventLogAnalyzer::IsVideoSsrc(StreamId stream_id) {
375 return video_ssrcs_.count(stream_id) == 1; 466 return video_ssrcs_.count(stream_id) == 1;
376 } 467 }
377 468
378 bool EventLogAnalyzer::IsAudioSsrc(StreamId stream_id) { 469 bool EventLogAnalyzer::IsAudioSsrc(StreamId stream_id) {
379 return audio_ssrcs_.count(stream_id) == 1; 470 return audio_ssrcs_.count(stream_id) == 1;
380 } 471 }
381 472
382 void EventLogAnalyzer::CreatePacketGraph(PacketDirection desired_direction, 473 void EventLogAnalyzer::CreatePacketGraph(PacketDirection desired_direction,
383 Plot* plot) { 474 Plot* plot) {
384 std::map<uint32_t, TimeSeries> time_series; 475 for (auto& kv : rtp_packets_) {
476 StreamId stream_id = kv.first;
477 const std::vector<LoggedRtpPacket>& packet_stream = kv.second;
478 // Filter on direction and SSRC.
479 if (stream_id.GetDirection() != desired_direction ||
480 !MatchingSsrc(stream_id.GetSsrc(), desired_ssrc_)) {
481 continue;
482 }
385 483
386 PacketDirection direction; 484 TimeSeries time_series;
387 MediaType media_type; 485 time_series.label = SsrcToString(stream_id.GetSsrc());
388 uint8_t header[IP_PACKET_SIZE]; 486 time_series.style = BAR_GRAPH;
389 size_t header_length, total_length; 487 Pointwise<PacketSizeBytes>(packet_stream, begin_time_, &time_series);
390 488 plot->series_list_.push_back(std::move(time_series));
391 for (size_t i = 0; i < parsed_log_.GetNumberOfEvents(); i++) {
392 ParsedRtcEventLog::EventType event_type = parsed_log_.GetEventType(i);
393 if (event_type == ParsedRtcEventLog::RTP_EVENT) {
394 parsed_log_.GetRtpHeader(i, &direction, &media_type, header,
395 &header_length, &total_length);
396 if (direction == desired_direction) {
397 // Parse header to get SSRC.
398 RtpUtility::RtpHeaderParser rtp_parser(header, header_length);
399 RTPHeader parsed_header;
400 rtp_parser.Parse(&parsed_header);
401 // Filter on SSRC.
402 if (MatchingSsrc(parsed_header.ssrc, desired_ssrc_)) {
403 uint64_t timestamp = parsed_log_.GetTimestamp(i);
404 float x = static_cast<float>(timestamp - begin_time_) / 1000000;
405 float y = total_length;
406 time_series[parsed_header.ssrc].points.push_back(
407 TimeSeriesPoint(x, y));
408 }
409 }
410 }
411 }
412
413 // Set labels and put in graph.
414 for (auto& kv : time_series) {
415 kv.second.label = SsrcToString(kv.first);
416 kv.second.style = BAR_GRAPH;
417 plot->series_list_.push_back(std::move(kv.second));
418 } 489 }
419 490
420 plot->SetXAxis(0, call_duration_s_, "Time (s)", kLeftMargin, kRightMargin); 491 plot->SetXAxis(0, call_duration_s_, "Time (s)", kLeftMargin, kRightMargin);
421 plot->SetSuggestedYAxis(0, 1, "Packet size (bytes)", kBottomMargin, 492 plot->SetSuggestedYAxis(0, 1, "Packet size (bytes)", kBottomMargin,
422 kTopMargin); 493 kTopMargin);
423 if (desired_direction == webrtc::PacketDirection::kIncomingPacket) { 494 if (desired_direction == webrtc::PacketDirection::kIncomingPacket) {
424 plot->SetTitle("Incoming RTP packets"); 495 plot->SetTitle("Incoming RTP packets");
425 } else if (desired_direction == webrtc::PacketDirection::kOutgoingPacket) { 496 } else if (desired_direction == webrtc::PacketDirection::kOutgoingPacket) {
426 plot->SetTitle("Outgoing RTP packets"); 497 plot->SetTitle("Outgoing RTP packets");
427 } 498 }
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
461 } 532 }
462 533
463 plot->SetXAxis(0, call_duration_s_, "Time (s)", kLeftMargin, kRightMargin); 534 plot->SetXAxis(0, call_duration_s_, "Time (s)", kLeftMargin, kRightMargin);
464 plot->SetSuggestedYAxis(0, 1, "Time since last playout (ms)", kBottomMargin, 535 plot->SetSuggestedYAxis(0, 1, "Time since last playout (ms)", kBottomMargin,
465 kTopMargin); 536 kTopMargin);
466 plot->SetTitle("Audio playout"); 537 plot->SetTitle("Audio playout");
467 } 538 }
468 539
469 // For each SSRC, plot the time between the consecutive playouts. 540 // For each SSRC, plot the time between the consecutive playouts.
470 void EventLogAnalyzer::CreateSequenceNumberGraph(Plot* plot) { 541 void EventLogAnalyzer::CreateSequenceNumberGraph(Plot* plot) {
471 std::map<uint32_t, TimeSeries> time_series; 542 for (auto& kv : rtp_packets_) {
472 std::map<uint32_t, uint16_t> last_seqno; 543 StreamId stream_id = kv.first;
544 const std::vector<LoggedRtpPacket>& packet_stream = kv.second;
545 // Filter on direction and SSRC.
546 if (stream_id.GetDirection() != kIncomingPacket ||
547 !MatchingSsrc(stream_id.GetSsrc(), desired_ssrc_)) {
548 continue;
549 }
473 550
474 PacketDirection direction; 551 TimeSeries time_series;
475 MediaType media_type; 552 time_series.label = SsrcToString(stream_id.GetSsrc());
476 uint8_t header[IP_PACKET_SIZE]; 553 time_series.style = BAR_GRAPH;
477 size_t header_length, total_length; 554 Pairwise<SequenceNumberDiff>(packet_stream, begin_time_, &time_series);
478 555 plot->series_list_.push_back(std::move(time_series));
479 for (size_t i = 0; i < parsed_log_.GetNumberOfEvents(); i++) {
480 ParsedRtcEventLog::EventType event_type = parsed_log_.GetEventType(i);
481 if (event_type == ParsedRtcEventLog::RTP_EVENT) {
482 parsed_log_.GetRtpHeader(i, &direction, &media_type, header,
483 &header_length, &total_length);
484 uint64_t timestamp = parsed_log_.GetTimestamp(i);
485 if (direction == PacketDirection::kIncomingPacket) {
486 // Parse header to get SSRC.
487 RtpUtility::RtpHeaderParser rtp_parser(header, header_length);
488 RTPHeader parsed_header;
489 rtp_parser.Parse(&parsed_header);
490 // Filter on SSRC.
491 if (MatchingSsrc(parsed_header.ssrc, desired_ssrc_)) {
492 float x = static_cast<float>(timestamp - begin_time_) / 1000000;
493 int y = WrappingDifference(parsed_header.sequenceNumber,
494 last_seqno[parsed_header.ssrc], 1ul << 16);
495 if (time_series[parsed_header.ssrc].points.size() == 0) {
496 // There were no previusly logged playout for this SSRC.
497 // Generate a point, but place it on the x-axis.
498 y = 0;
499 }
500 time_series[parsed_header.ssrc].points.push_back(
501 TimeSeriesPoint(x, y));
502 last_seqno[parsed_header.ssrc] = parsed_header.sequenceNumber;
503 }
504 }
505 }
506 }
507
508 // Set labels and put in graph.
509 for (auto& kv : time_series) {
510 kv.second.label = SsrcToString(kv.first);
511 kv.second.style = BAR_GRAPH;
512 plot->series_list_.push_back(std::move(kv.second));
513 } 556 }
514 557
515 plot->SetXAxis(0, call_duration_s_, "Time (s)", kLeftMargin, kRightMargin); 558 plot->SetXAxis(0, call_duration_s_, "Time (s)", kLeftMargin, kRightMargin);
516 plot->SetSuggestedYAxis(0, 1, "Difference since last packet", kBottomMargin, 559 plot->SetSuggestedYAxis(0, 1, "Difference since last packet", kBottomMargin,
517 kTopMargin); 560 kTopMargin);
518 plot->SetTitle("Sequence number"); 561 plot->SetTitle("Sequence number");
519 } 562 }
520 563
521 void EventLogAnalyzer::CreateDelayChangeGraph(Plot* plot) { 564 void EventLogAnalyzer::CreateDelayChangeGraph(Plot* plot) {
522 for (auto& kv : rtp_packets_) { 565 for (auto& kv : rtp_packets_) {
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after
631 size_t window_index_begin = 0; 674 size_t window_index_begin = 0;
632 size_t window_index_end = 0; 675 size_t window_index_end = 0;
633 size_t bytes_in_window = 0; 676 size_t bytes_in_window = 0;
634 677
635 // Calculate a moving average of the bitrate and store in a TimeSeries. 678 // Calculate a moving average of the bitrate and store in a TimeSeries.
636 plot->series_list_.push_back(TimeSeries()); 679 plot->series_list_.push_back(TimeSeries());
637 for (uint64_t time = begin_time_; time < end_time_ + step_; time += step_) { 680 for (uint64_t time = begin_time_; time < end_time_ + step_; time += step_) {
638 while (window_index_end < packets.size() && 681 while (window_index_end < packets.size() &&
639 packets[window_index_end].timestamp < time) { 682 packets[window_index_end].timestamp < time) {
640 bytes_in_window += packets[window_index_end].size; 683 bytes_in_window += packets[window_index_end].size;
641 window_index_end++; 684 ++window_index_end;
642 } 685 }
643 while (window_index_begin < packets.size() && 686 while (window_index_begin < packets.size() &&
644 packets[window_index_begin].timestamp < time - window_duration_) { 687 packets[window_index_begin].timestamp < time - window_duration_) {
645 RTC_DCHECK_LE(packets[window_index_begin].size, bytes_in_window); 688 RTC_DCHECK_LE(packets[window_index_begin].size, bytes_in_window);
646 bytes_in_window -= packets[window_index_begin].size; 689 bytes_in_window -= packets[window_index_begin].size;
647 window_index_begin++; 690 ++window_index_begin;
648 } 691 }
649 float window_duration_in_seconds = 692 float window_duration_in_seconds =
650 static_cast<float>(window_duration_) / 1000000; 693 static_cast<float>(window_duration_) / 1000000;
651 float x = static_cast<float>(time - begin_time_) / 1000000; 694 float x = static_cast<float>(time - begin_time_) / 1000000;
652 float y = bytes_in_window * 8 / window_duration_in_seconds / 1000; 695 float y = bytes_in_window * 8 / window_duration_in_seconds / 1000;
653 plot->series_list_.back().points.push_back(TimeSeriesPoint(x, y)); 696 plot->series_list_.back().points.push_back(TimeSeriesPoint(x, y));
654 } 697 }
655 698
656 // Set labels. 699 // Set labels.
657 if (desired_direction == webrtc::PacketDirection::kIncomingPacket) { 700 if (desired_direction == webrtc::PacketDirection::kIncomingPacket) {
(...skipping 22 matching lines...) Expand all
680 plot->SetTitle("Incoming RTP bitrate"); 723 plot->SetTitle("Incoming RTP bitrate");
681 } else if (desired_direction == webrtc::PacketDirection::kOutgoingPacket) { 724 } else if (desired_direction == webrtc::PacketDirection::kOutgoingPacket) {
682 plot->SetTitle("Outgoing RTP bitrate"); 725 plot->SetTitle("Outgoing RTP bitrate");
683 } 726 }
684 } 727 }
685 728
686 // For each SSRC, plot the bandwidth used by that stream. 729 // For each SSRC, plot the bandwidth used by that stream.
687 void EventLogAnalyzer::CreateStreamBitrateGraph( 730 void EventLogAnalyzer::CreateStreamBitrateGraph(
688 PacketDirection desired_direction, 731 PacketDirection desired_direction,
689 Plot* plot) { 732 Plot* plot) {
690 struct TimestampSize { 733 for (auto& kv : rtp_packets_) {
691 TimestampSize(uint64_t t, size_t s) : timestamp(t), size(s) {} 734 StreamId stream_id = kv.first;
692 uint64_t timestamp; 735 const std::vector<LoggedRtpPacket>& packet_stream = kv.second;
693 size_t size; 736 // Filter on direction and SSRC.
694 }; 737 if (stream_id.GetDirection() != desired_direction ||
695 std::map<uint32_t, std::vector<TimestampSize>> packets; 738 !MatchingSsrc(stream_id.GetSsrc(), desired_ssrc_)) {
696 739 continue;
697 PacketDirection direction;
698 MediaType media_type;
699 uint8_t header[IP_PACKET_SIZE];
700 size_t header_length, total_length;
701
702 // Extract timestamps and sizes for the relevant packets.
703 for (size_t i = 0; i < parsed_log_.GetNumberOfEvents(); i++) {
704 ParsedRtcEventLog::EventType event_type = parsed_log_.GetEventType(i);
705 if (event_type == ParsedRtcEventLog::RTP_EVENT) {
706 parsed_log_.GetRtpHeader(i, &direction, &media_type, header,
707 &header_length, &total_length);
708 if (direction == desired_direction) {
709 // Parse header to get SSRC.
710 RtpUtility::RtpHeaderParser rtp_parser(header, header_length);
711 RTPHeader parsed_header;
712 rtp_parser.Parse(&parsed_header);
713 // Filter on SSRC.
714 if (MatchingSsrc(parsed_header.ssrc, desired_ssrc_)) {
715 uint64_t timestamp = parsed_log_.GetTimestamp(i);
716 packets[parsed_header.ssrc].push_back(
717 TimestampSize(timestamp, total_length));
718 }
719 }
720 }
721 }
722
723 for (auto& kv : packets) {
724 size_t window_index_begin = 0;
725 size_t window_index_end = 0;
726 size_t bytes_in_window = 0;
727
728 // Calculate a moving average of the bitrate and store in a TimeSeries.
729 plot->series_list_.push_back(TimeSeries());
730 for (uint64_t time = begin_time_; time < end_time_ + step_; time += step_) {
731 while (window_index_end < kv.second.size() &&
732 kv.second[window_index_end].timestamp < time) {
733 bytes_in_window += kv.second[window_index_end].size;
734 window_index_end++;
735 }
736 while (window_index_begin < kv.second.size() &&
737 kv.second[window_index_begin].timestamp <
738 time - window_duration_) {
739 RTC_DCHECK_LE(kv.second[window_index_begin].size, bytes_in_window);
740 bytes_in_window -= kv.second[window_index_begin].size;
741 window_index_begin++;
742 }
743 float window_duration_in_seconds =
744 static_cast<float>(window_duration_) / 1000000;
745 float x = static_cast<float>(time - begin_time_) / 1000000;
746 float y = bytes_in_window * 8 / window_duration_in_seconds / 1000;
747 plot->series_list_.back().points.push_back(TimeSeriesPoint(x, y));
748 } 740 }
749 741
750 // Set labels. 742 TimeSeries time_series;
751 plot->series_list_.back().label = SsrcToString(kv.first); 743 time_series.label = SsrcToString(stream_id.GetSsrc());
752 plot->series_list_.back().style = LINE_GRAPH; 744 time_series.style = LINE_GRAPH;
745 double bytes_to_kilobits = 8.0 / 1000;
746 MovingAverage<PacketSizeBytes>(packet_stream, begin_time_, end_time_,
747 window_duration_, step_, bytes_to_kilobits,
748 &time_series);
749 plot->series_list_.push_back(std::move(time_series));
753 } 750 }
754 751
755 plot->SetXAxis(0, call_duration_s_, "Time (s)", kLeftMargin, kRightMargin); 752 plot->SetXAxis(0, call_duration_s_, "Time (s)", kLeftMargin, kRightMargin);
756 plot->SetSuggestedYAxis(0, 1, "Bitrate (kbps)", kBottomMargin, kTopMargin); 753 plot->SetSuggestedYAxis(0, 1, "Bitrate (kbps)", kBottomMargin, kTopMargin);
757 if (desired_direction == webrtc::PacketDirection::kIncomingPacket) { 754 if (desired_direction == webrtc::PacketDirection::kIncomingPacket) {
758 plot->SetTitle("Incoming bitrate per stream"); 755 plot->SetTitle("Incoming bitrate per stream");
759 } else if (desired_direction == webrtc::PacketDirection::kOutgoingPacket) { 756 } else if (desired_direction == webrtc::PacketDirection::kOutgoingPacket) {
760 plot->SetTitle("Outgoing bitrate per stream"); 757 plot->SetTitle("Outgoing bitrate per stream");
761 } 758 }
762 } 759 }
(...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after
945 point.y -= estimated_base_delay_ms; 942 point.y -= estimated_base_delay_ms;
946 // Add the data set to the plot. 943 // Add the data set to the plot.
947 plot->series_list_.push_back(std::move(time_series)); 944 plot->series_list_.push_back(std::move(time_series));
948 945
949 plot->SetXAxis(0, call_duration_s_, "Time (s)", kLeftMargin, kRightMargin); 946 plot->SetXAxis(0, call_duration_s_, "Time (s)", kLeftMargin, kRightMargin);
950 plot->SetSuggestedYAxis(0, 10, "Delay (ms)", kBottomMargin, kTopMargin); 947 plot->SetSuggestedYAxis(0, 10, "Delay (ms)", kBottomMargin, kTopMargin);
951 plot->SetTitle("Network Delay Change."); 948 plot->SetTitle("Network Delay Change.");
952 } 949 }
953 } // namespace plotting 950 } // namespace plotting
954 } // namespace webrtc 951 } // namespace webrtc
OLDNEW
« 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