Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 10 matching lines...) Expand all Loading... | |
| 21 #include "webrtc/audio_send_stream.h" | 21 #include "webrtc/audio_send_stream.h" |
| 22 #include "webrtc/base/checks.h" | 22 #include "webrtc/base/checks.h" |
| 23 #include "webrtc/call.h" | 23 #include "webrtc/call.h" |
| 24 #include "webrtc/common_types.h" | 24 #include "webrtc/common_types.h" |
| 25 #include "webrtc/modules/rtp_rtcp/include/rtp_rtcp.h" | 25 #include "webrtc/modules/rtp_rtcp/include/rtp_rtcp.h" |
| 26 #include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" | 26 #include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" |
| 27 #include "webrtc/modules/rtp_rtcp/source/rtp_utility.h" | 27 #include "webrtc/modules/rtp_rtcp/source/rtp_utility.h" |
| 28 #include "webrtc/video_receive_stream.h" | 28 #include "webrtc/video_receive_stream.h" |
| 29 #include "webrtc/video_send_stream.h" | 29 #include "webrtc/video_send_stream.h" |
| 30 | 30 |
| 31 namespace { | 31 namespace { |
|
danilchap
2016/07/26 10:52:46
it is recommended to have unnamed namespace inside
terelius
2016/07/26 17:37:38
Done.
| |
| 32 | 32 |
| 33 std::string SsrcToString(uint32_t ssrc) { | 33 std::string SsrcToString(uint32_t ssrc) { |
| 34 std::stringstream ss; | 34 std::stringstream ss; |
| 35 ss << "SSRC " << ssrc; | 35 ss << "SSRC " << ssrc; |
| 36 return ss.str(); | 36 return ss.str(); |
| 37 } | 37 } |
| 38 | 38 |
| 39 // Checks whether an SSRC is contained in the list of desired SSRCs. | 39 // Checks whether an SSRC is contained in the list of desired SSRCs. |
| 40 // Note that an empty SSRC list matches every SSRC. | 40 // Note that an empty SSRC list matches every SSRC. |
| 41 bool MatchingSsrc(uint32_t ssrc, const std::vector<uint32_t>& desired_ssrc) { | 41 bool MatchingSsrc(uint32_t ssrc, const std::vector<uint32_t>& desired_ssrc) { |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 69 int64_t min_difference = max_difference - modulus + 1; | 69 int64_t min_difference = max_difference - modulus + 1; |
| 70 if (difference > max_difference) { | 70 if (difference > max_difference) { |
| 71 difference -= modulus; | 71 difference -= modulus; |
| 72 } | 72 } |
| 73 if (difference < min_difference) { | 73 if (difference < min_difference) { |
| 74 difference += modulus; | 74 difference += modulus; |
| 75 } | 75 } |
| 76 return difference; | 76 return difference; |
| 77 } | 77 } |
| 78 | 78 |
| 79 const double kXMargin = 1.02; | 79 const float kLeftMargin = 0.01; |
|
danilchap
2016/07/26 10:52:46
can be constexpr
terelius
2016/07/26 17:37:38
Done.
| |
| 80 const double kYMargin = 1.1; | 80 const float kRightMargin = 0.02; |
| 81 const double kDefaultXMin = -1; | 81 const float kBottomMargin = 0.02; |
| 82 const double kDefaultYMin = -1; | 82 const float kTopMargin = 0.05; |
| 83 | 83 |
| 84 } // namespace | 84 } // namespace |
| 85 | 85 |
| 86 namespace webrtc { | 86 namespace webrtc { |
| 87 namespace plotting { | 87 namespace plotting { |
| 88 | 88 |
| 89 | 89 |
| 90 bool EventLogAnalyzer::StreamId::operator<(const StreamId& other) const { | 90 bool EventLogAnalyzer::StreamId::operator<(const StreamId& other) const { |
| 91 if (ssrc_ < other.ssrc_) { | 91 if (ssrc_ < other.ssrc_) { |
| 92 return true; | 92 return true; |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 223 } | 223 } |
| 224 } | 224 } |
| 225 } | 225 } |
| 226 | 226 |
| 227 if (last_timestamp < first_timestamp) { | 227 if (last_timestamp < first_timestamp) { |
| 228 // No useful events in the log. | 228 // No useful events in the log. |
| 229 first_timestamp = last_timestamp = 0; | 229 first_timestamp = last_timestamp = 0; |
| 230 } | 230 } |
| 231 begin_time_ = first_timestamp; | 231 begin_time_ = first_timestamp; |
| 232 end_time_ = last_timestamp; | 232 end_time_ = last_timestamp; |
| 233 call_duration_s_ = static_cast<float>(end_time_ - begin_time_) / 1000000; | |
| 233 } | 234 } |
| 234 | 235 |
| 235 void EventLogAnalyzer::CreatePacketGraph(PacketDirection desired_direction, | 236 void EventLogAnalyzer::CreatePacketGraph(PacketDirection desired_direction, |
| 236 Plot* plot) { | 237 Plot* plot) { |
| 237 std::map<uint32_t, TimeSeries> time_series; | 238 std::map<uint32_t, TimeSeries> time_series; |
| 238 | 239 |
| 239 PacketDirection direction; | 240 PacketDirection direction; |
| 240 MediaType media_type; | 241 MediaType media_type; |
| 241 uint8_t header[IP_PACKET_SIZE]; | 242 uint8_t header[IP_PACKET_SIZE]; |
| 242 size_t header_length, total_length; | 243 size_t header_length, total_length; |
| 243 float max_y = 0; | |
| 244 | 244 |
| 245 for (size_t i = 0; i < parsed_log_.GetNumberOfEvents(); i++) { | 245 for (size_t i = 0; i < parsed_log_.GetNumberOfEvents(); i++) { |
| 246 ParsedRtcEventLog::EventType event_type = parsed_log_.GetEventType(i); | 246 ParsedRtcEventLog::EventType event_type = parsed_log_.GetEventType(i); |
| 247 if (event_type == ParsedRtcEventLog::RTP_EVENT) { | 247 if (event_type == ParsedRtcEventLog::RTP_EVENT) { |
| 248 parsed_log_.GetRtpHeader(i, &direction, &media_type, header, | 248 parsed_log_.GetRtpHeader(i, &direction, &media_type, header, |
| 249 &header_length, &total_length); | 249 &header_length, &total_length); |
| 250 if (direction == desired_direction) { | 250 if (direction == desired_direction) { |
| 251 // Parse header to get SSRC. | 251 // Parse header to get SSRC. |
| 252 RtpUtility::RtpHeaderParser rtp_parser(header, header_length); | 252 RtpUtility::RtpHeaderParser rtp_parser(header, header_length); |
| 253 RTPHeader parsed_header; | 253 RTPHeader parsed_header; |
| 254 rtp_parser.Parse(&parsed_header); | 254 rtp_parser.Parse(&parsed_header); |
| 255 // Filter on SSRC. | 255 // Filter on SSRC. |
| 256 if (MatchingSsrc(parsed_header.ssrc, desired_ssrc_)) { | 256 if (MatchingSsrc(parsed_header.ssrc, desired_ssrc_)) { |
| 257 uint64_t timestamp = parsed_log_.GetTimestamp(i); | 257 uint64_t timestamp = parsed_log_.GetTimestamp(i); |
| 258 float x = static_cast<float>(timestamp - begin_time_) / 1000000; | 258 float x = static_cast<float>(timestamp - begin_time_) / 1000000; |
| 259 float y = total_length; | 259 float y = total_length; |
| 260 max_y = std::max(max_y, y); | |
| 261 time_series[parsed_header.ssrc].points.push_back( | 260 time_series[parsed_header.ssrc].points.push_back( |
| 262 TimeSeriesPoint(x, y)); | 261 TimeSeriesPoint(x, y)); |
| 263 } | 262 } |
| 264 } | 263 } |
| 265 } | 264 } |
| 266 } | 265 } |
| 267 | 266 |
| 268 // Set labels and put in graph. | 267 // Set labels and put in graph. |
| 269 for (auto& kv : time_series) { | 268 for (auto& kv : time_series) { |
| 270 kv.second.label = SsrcToString(kv.first); | 269 kv.second.label = SsrcToString(kv.first); |
| 271 kv.second.style = BAR_GRAPH; | 270 kv.second.style = BAR_GRAPH; |
| 272 plot->series.push_back(std::move(kv.second)); | 271 plot->series_list_.push_back(std::move(kv.second)); |
| 273 } | 272 } |
| 274 | 273 |
| 275 plot->xaxis_min = kDefaultXMin; | 274 plot->SetXAxis(0, call_duration_s_, "Time (s)", kLeftMargin, kRightMargin); |
| 276 plot->xaxis_max = (end_time_ - begin_time_) / 1000000 * kXMargin; | 275 plot->SetSuggestedYAxis(0, 1, "Packet size (bytes)", kBottomMargin, |
| 277 plot->xaxis_label = "Time (s)"; | 276 kTopMargin); |
| 278 plot->yaxis_min = kDefaultYMin; | |
| 279 plot->yaxis_max = max_y * kYMargin; | |
| 280 plot->yaxis_label = "Packet size (bytes)"; | |
| 281 if (desired_direction == webrtc::PacketDirection::kIncomingPacket) { | 277 if (desired_direction == webrtc::PacketDirection::kIncomingPacket) { |
| 282 plot->title = "Incoming RTP packets"; | 278 plot->SetTitle("Incoming RTP packets"); |
| 283 } else if (desired_direction == webrtc::PacketDirection::kOutgoingPacket) { | 279 } else if (desired_direction == webrtc::PacketDirection::kOutgoingPacket) { |
| 284 plot->title = "Outgoing RTP packets"; | 280 plot->SetTitle("Outgoing RTP packets"); |
| 285 } | 281 } |
| 286 } | 282 } |
| 287 | 283 |
| 288 // For each SSRC, plot the time between the consecutive playouts. | 284 // For each SSRC, plot the time between the consecutive playouts. |
| 289 void EventLogAnalyzer::CreatePlayoutGraph(Plot* plot) { | 285 void EventLogAnalyzer::CreatePlayoutGraph(Plot* plot) { |
| 290 std::map<uint32_t, TimeSeries> time_series; | 286 std::map<uint32_t, TimeSeries> time_series; |
| 291 std::map<uint32_t, uint64_t> last_playout; | 287 std::map<uint32_t, uint64_t> last_playout; |
| 292 | 288 |
| 293 uint32_t ssrc; | 289 uint32_t ssrc; |
| 294 float max_y = 0; | |
| 295 | 290 |
| 296 for (size_t i = 0; i < parsed_log_.GetNumberOfEvents(); i++) { | 291 for (size_t i = 0; i < parsed_log_.GetNumberOfEvents(); i++) { |
| 297 ParsedRtcEventLog::EventType event_type = parsed_log_.GetEventType(i); | 292 ParsedRtcEventLog::EventType event_type = parsed_log_.GetEventType(i); |
| 298 if (event_type == ParsedRtcEventLog::AUDIO_PLAYOUT_EVENT) { | 293 if (event_type == ParsedRtcEventLog::AUDIO_PLAYOUT_EVENT) { |
| 299 parsed_log_.GetAudioPlayout(i, &ssrc); | 294 parsed_log_.GetAudioPlayout(i, &ssrc); |
| 300 uint64_t timestamp = parsed_log_.GetTimestamp(i); | 295 uint64_t timestamp = parsed_log_.GetTimestamp(i); |
| 301 if (MatchingSsrc(ssrc, desired_ssrc_)) { | 296 if (MatchingSsrc(ssrc, desired_ssrc_)) { |
| 302 float x = static_cast<float>(timestamp - begin_time_) / 1000000; | 297 float x = static_cast<float>(timestamp - begin_time_) / 1000000; |
| 303 float y = static_cast<float>(timestamp - last_playout[ssrc]) / 1000; | 298 float y = static_cast<float>(timestamp - last_playout[ssrc]) / 1000; |
| 304 if (time_series[ssrc].points.size() == 0) { | 299 if (time_series[ssrc].points.size() == 0) { |
| 305 // There were no previusly logged playout for this SSRC. | 300 // There were no previusly logged playout for this SSRC. |
| 306 // Generate a point, but place it on the x-axis. | 301 // Generate a point, but place it on the x-axis. |
| 307 y = 0; | 302 y = 0; |
| 308 } | 303 } |
| 309 max_y = std::max(max_y, y); | |
| 310 time_series[ssrc].points.push_back(TimeSeriesPoint(x, y)); | 304 time_series[ssrc].points.push_back(TimeSeriesPoint(x, y)); |
| 311 last_playout[ssrc] = timestamp; | 305 last_playout[ssrc] = timestamp; |
| 312 } | 306 } |
| 313 } | 307 } |
| 314 } | 308 } |
| 315 | 309 |
| 316 // Set labels and put in graph. | 310 // Set labels and put in graph. |
| 317 for (auto& kv : time_series) { | 311 for (auto& kv : time_series) { |
| 318 kv.second.label = SsrcToString(kv.first); | 312 kv.second.label = SsrcToString(kv.first); |
| 319 kv.second.style = BAR_GRAPH; | 313 kv.second.style = BAR_GRAPH; |
| 320 plot->series.push_back(std::move(kv.second)); | 314 plot->series_list_.push_back(std::move(kv.second)); |
| 321 } | 315 } |
| 322 | 316 |
| 323 plot->xaxis_min = kDefaultXMin; | 317 plot->SetXAxis(0, call_duration_s_, "Time (s)", kLeftMargin, kRightMargin); |
| 324 plot->xaxis_max = (end_time_ - begin_time_) / 1000000 * kXMargin; | 318 plot->SetSuggestedYAxis(0, 1, "Time since last playout (ms)", kBottomMargin, |
| 325 plot->xaxis_label = "Time (s)"; | 319 kTopMargin); |
| 326 plot->yaxis_min = kDefaultYMin; | 320 plot->SetTitle("Audio playout"); |
| 327 plot->yaxis_max = max_y * kYMargin; | |
| 328 plot->yaxis_label = "Time since last playout (ms)"; | |
| 329 plot->title = "Audio playout"; | |
| 330 } | 321 } |
| 331 | 322 |
| 332 // For each SSRC, plot the time between the consecutive playouts. | 323 // For each SSRC, plot the time between the consecutive playouts. |
| 333 void EventLogAnalyzer::CreateSequenceNumberGraph(Plot* plot) { | 324 void EventLogAnalyzer::CreateSequenceNumberGraph(Plot* plot) { |
| 334 std::map<uint32_t, TimeSeries> time_series; | 325 std::map<uint32_t, TimeSeries> time_series; |
| 335 std::map<uint32_t, uint16_t> last_seqno; | 326 std::map<uint32_t, uint16_t> last_seqno; |
| 336 | 327 |
| 337 PacketDirection direction; | 328 PacketDirection direction; |
| 338 MediaType media_type; | 329 MediaType media_type; |
| 339 uint8_t header[IP_PACKET_SIZE]; | 330 uint8_t header[IP_PACKET_SIZE]; |
| 340 size_t header_length, total_length; | 331 size_t header_length, total_length; |
| 341 | 332 |
| 342 int max_y = 1; | |
| 343 int min_y = 0; | |
| 344 | |
| 345 for (size_t i = 0; i < parsed_log_.GetNumberOfEvents(); i++) { | 333 for (size_t i = 0; i < parsed_log_.GetNumberOfEvents(); i++) { |
| 346 ParsedRtcEventLog::EventType event_type = parsed_log_.GetEventType(i); | 334 ParsedRtcEventLog::EventType event_type = parsed_log_.GetEventType(i); |
| 347 if (event_type == ParsedRtcEventLog::RTP_EVENT) { | 335 if (event_type == ParsedRtcEventLog::RTP_EVENT) { |
| 348 parsed_log_.GetRtpHeader(i, &direction, &media_type, header, | 336 parsed_log_.GetRtpHeader(i, &direction, &media_type, header, |
| 349 &header_length, &total_length); | 337 &header_length, &total_length); |
| 350 uint64_t timestamp = parsed_log_.GetTimestamp(i); | 338 uint64_t timestamp = parsed_log_.GetTimestamp(i); |
| 351 if (direction == PacketDirection::kIncomingPacket) { | 339 if (direction == PacketDirection::kIncomingPacket) { |
| 352 // Parse header to get SSRC. | 340 // Parse header to get SSRC. |
| 353 RtpUtility::RtpHeaderParser rtp_parser(header, header_length); | 341 RtpUtility::RtpHeaderParser rtp_parser(header, header_length); |
| 354 RTPHeader parsed_header; | 342 RTPHeader parsed_header; |
| 355 rtp_parser.Parse(&parsed_header); | 343 rtp_parser.Parse(&parsed_header); |
| 356 // Filter on SSRC. | 344 // Filter on SSRC. |
| 357 if (MatchingSsrc(parsed_header.ssrc, desired_ssrc_)) { | 345 if (MatchingSsrc(parsed_header.ssrc, desired_ssrc_)) { |
| 358 float x = static_cast<float>(timestamp - begin_time_) / 1000000; | 346 float x = static_cast<float>(timestamp - begin_time_) / 1000000; |
| 359 int y = WrappingDifference(parsed_header.sequenceNumber, | 347 int y = WrappingDifference(parsed_header.sequenceNumber, |
| 360 last_seqno[parsed_header.ssrc], 1ul << 16); | 348 last_seqno[parsed_header.ssrc], 1ul << 16); |
| 361 if (time_series[parsed_header.ssrc].points.size() == 0) { | 349 if (time_series[parsed_header.ssrc].points.size() == 0) { |
| 362 // There were no previusly logged playout for this SSRC. | 350 // There were no previusly logged playout for this SSRC. |
| 363 // Generate a point, but place it on the x-axis. | 351 // Generate a point, but place it on the x-axis. |
| 364 y = 0; | 352 y = 0; |
| 365 } | 353 } |
| 366 max_y = std::max(max_y, y); | |
| 367 min_y = std::min(min_y, y); | |
| 368 time_series[parsed_header.ssrc].points.push_back( | 354 time_series[parsed_header.ssrc].points.push_back( |
| 369 TimeSeriesPoint(x, y)); | 355 TimeSeriesPoint(x, y)); |
| 370 last_seqno[parsed_header.ssrc] = parsed_header.sequenceNumber; | 356 last_seqno[parsed_header.ssrc] = parsed_header.sequenceNumber; |
| 371 } | 357 } |
| 372 } | 358 } |
| 373 } | 359 } |
| 374 } | 360 } |
| 375 | 361 |
| 376 // Set labels and put in graph. | 362 // Set labels and put in graph. |
| 377 for (auto& kv : time_series) { | 363 for (auto& kv : time_series) { |
| 378 kv.second.label = SsrcToString(kv.first); | 364 kv.second.label = SsrcToString(kv.first); |
| 379 kv.second.style = BAR_GRAPH; | 365 kv.second.style = BAR_GRAPH; |
| 380 plot->series.push_back(std::move(kv.second)); | 366 plot->series_list_.push_back(std::move(kv.second)); |
| 381 } | 367 } |
| 382 | 368 |
| 383 plot->xaxis_min = kDefaultXMin; | 369 plot->SetXAxis(0, call_duration_s_, "Time (s)", kLeftMargin, kRightMargin); |
| 384 plot->xaxis_max = (end_time_ - begin_time_) / 1000000 * kXMargin; | 370 plot->SetSuggestedYAxis(0, 1, "Difference since last packet", kBottomMargin, |
| 385 plot->xaxis_label = "Time (s)"; | 371 kTopMargin); |
| 386 plot->yaxis_min = min_y - (kYMargin - 1) / 2 * (max_y - min_y); | 372 plot->SetTitle("Sequence number"); |
| 387 plot->yaxis_max = max_y + (kYMargin - 1) / 2 * (max_y - min_y); | |
| 388 plot->yaxis_label = "Difference since last packet"; | |
| 389 plot->title = "Sequence number"; | |
| 390 } | 373 } |
| 391 | 374 |
| 392 void EventLogAnalyzer::CreateDelayChangeGraph(Plot* plot) { | 375 void EventLogAnalyzer::CreateDelayChangeGraph(Plot* plot) { |
| 393 double max_y = 10; | |
| 394 double min_y = 0; | |
| 395 | |
| 396 for (auto& kv : rtp_packets_) { | 376 for (auto& kv : rtp_packets_) { |
| 397 StreamId stream_id = kv.first; | 377 StreamId stream_id = kv.first; |
| 398 // Filter on direction and SSRC. | 378 // Filter on direction and SSRC. |
| 399 if (stream_id.GetDirection() != kIncomingPacket || | 379 if (stream_id.GetDirection() != kIncomingPacket || |
| 400 !MatchingSsrc(stream_id.GetSsrc(), desired_ssrc_)) { | 380 !MatchingSsrc(stream_id.GetSsrc(), desired_ssrc_)) { |
| 401 continue; | 381 continue; |
| 402 } | 382 } |
| 403 | 383 |
| 404 TimeSeries time_series; | 384 TimeSeries time_series; |
| 405 time_series.label = SsrcToString(stream_id.GetSsrc()); | 385 time_series.label = SsrcToString(stream_id.GetSsrc()); |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 420 float x = static_cast<float>(packet.timestamp - begin_time_) / 1000000; | 400 float x = static_cast<float>(packet.timestamp - begin_time_) / 1000000; |
| 421 double y = | 401 double y = |
| 422 static_cast<double>(recv_time_diff - | 402 static_cast<double>(recv_time_diff - |
| 423 AbsSendTimeToMicroseconds(send_time_diff)) / | 403 AbsSendTimeToMicroseconds(send_time_diff)) / |
| 424 1000; | 404 1000; |
| 425 if (time_series.points.size() == 0) { | 405 if (time_series.points.size() == 0) { |
| 426 // There were no previously logged packets for this SSRC. | 406 // There were no previously logged packets for this SSRC. |
| 427 // Generate a point, but place it on the x-axis. | 407 // Generate a point, but place it on the x-axis. |
| 428 y = 0; | 408 y = 0; |
| 429 } | 409 } |
| 430 max_y = std::max(max_y, y); | |
| 431 min_y = std::min(min_y, y); | |
| 432 time_series.points.emplace_back(x, y); | 410 time_series.points.emplace_back(x, y); |
| 433 } | 411 } |
| 434 } | 412 } |
| 435 // Add the data set to the plot. | 413 // Add the data set to the plot. |
| 436 plot->series.push_back(std::move(time_series)); | 414 plot->series_list_.push_back(std::move(time_series)); |
| 437 } | 415 } |
| 438 | 416 |
| 439 plot->xaxis_min = kDefaultXMin; | 417 plot->SetXAxis(0, call_duration_s_, "Time (s)", kLeftMargin, kRightMargin); |
| 440 plot->xaxis_max = (end_time_ - begin_time_) / 1000000 * kXMargin; | 418 plot->SetSuggestedYAxis(0, 1, "Latency change (ms)", kBottomMargin, |
| 441 plot->xaxis_label = "Time (s)"; | 419 kTopMargin); |
| 442 plot->yaxis_min = min_y - (kYMargin - 1) / 2 * (max_y - min_y); | 420 plot->SetTitle("Network latency change between consecutive packets"); |
| 443 plot->yaxis_max = max_y + (kYMargin - 1) / 2 * (max_y - min_y); | |
| 444 plot->yaxis_label = "Latency change (ms)"; | |
| 445 plot->title = "Network latency change between consecutive packets"; | |
| 446 } | 421 } |
| 447 | 422 |
| 448 void EventLogAnalyzer::CreateAccumulatedDelayChangeGraph(Plot* plot) { | 423 void EventLogAnalyzer::CreateAccumulatedDelayChangeGraph(Plot* plot) { |
| 449 double max_y = 10; | |
| 450 double min_y = 0; | |
| 451 | |
| 452 for (auto& kv : rtp_packets_) { | 424 for (auto& kv : rtp_packets_) { |
| 453 StreamId stream_id = kv.first; | 425 StreamId stream_id = kv.first; |
| 454 // Filter on direction and SSRC. | 426 // Filter on direction and SSRC. |
| 455 if (stream_id.GetDirection() != kIncomingPacket || | 427 if (stream_id.GetDirection() != kIncomingPacket || |
| 456 !MatchingSsrc(stream_id.GetSsrc(), desired_ssrc_)) { | 428 !MatchingSsrc(stream_id.GetSsrc(), desired_ssrc_)) { |
| 457 continue; | 429 continue; |
| 458 } | 430 } |
| 459 TimeSeries time_series; | 431 TimeSeries time_series; |
| 460 time_series.label = SsrcToString(stream_id.GetSsrc()); | 432 time_series.label = SsrcToString(stream_id.GetSsrc()); |
| 461 time_series.style = LINE_GRAPH; | 433 time_series.style = LINE_GRAPH; |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 476 float x = static_cast<float>(packet.timestamp - begin_time_) / 1000000; | 448 float x = static_cast<float>(packet.timestamp - begin_time_) / 1000000; |
| 477 accumulated_delay_ms += | 449 accumulated_delay_ms += |
| 478 static_cast<double>(recv_time_diff - | 450 static_cast<double>(recv_time_diff - |
| 479 AbsSendTimeToMicroseconds(send_time_diff)) / | 451 AbsSendTimeToMicroseconds(send_time_diff)) / |
| 480 1000; | 452 1000; |
| 481 if (time_series.points.size() == 0) { | 453 if (time_series.points.size() == 0) { |
| 482 // There were no previously logged packets for this SSRC. | 454 // There were no previously logged packets for this SSRC. |
| 483 // Generate a point, but place it on the x-axis. | 455 // Generate a point, but place it on the x-axis. |
| 484 accumulated_delay_ms = 0; | 456 accumulated_delay_ms = 0; |
| 485 } | 457 } |
| 486 max_y = std::max(max_y, accumulated_delay_ms); | |
| 487 min_y = std::min(min_y, accumulated_delay_ms); | |
| 488 time_series.points.emplace_back(x, accumulated_delay_ms); | 458 time_series.points.emplace_back(x, accumulated_delay_ms); |
| 489 } | 459 } |
| 490 } | 460 } |
| 491 // Add the data set to the plot. | 461 // Add the data set to the plot. |
| 492 plot->series.push_back(std::move(time_series)); | 462 plot->series_list_.push_back(std::move(time_series)); |
| 493 } | 463 } |
| 494 | 464 |
| 495 plot->xaxis_min = kDefaultXMin; | 465 plot->SetXAxis(0, call_duration_s_, "Time (s)", kLeftMargin, kRightMargin); |
| 496 plot->xaxis_max = (end_time_ - begin_time_) / 1000000 * kXMargin; | 466 plot->SetSuggestedYAxis(0, 1, "Latency change (ms)", kBottomMargin, |
| 497 plot->xaxis_label = "Time (s)"; | 467 kTopMargin); |
| 498 plot->yaxis_min = min_y - (kYMargin - 1) / 2 * (max_y - min_y); | 468 plot->SetTitle("Accumulated network latency change"); |
| 499 plot->yaxis_max = max_y + (kYMargin - 1) / 2 * (max_y - min_y); | |
| 500 plot->yaxis_label = "Latency change (ms)"; | |
| 501 plot->title = "Accumulated network latency change"; | |
| 502 } | 469 } |
| 503 | 470 |
| 504 // Plot the total bandwidth used by all RTP streams. | 471 // Plot the total bandwidth used by all RTP streams. |
| 505 void EventLogAnalyzer::CreateTotalBitrateGraph( | 472 void EventLogAnalyzer::CreateTotalBitrateGraph( |
| 506 PacketDirection desired_direction, | 473 PacketDirection desired_direction, |
| 507 Plot* plot) { | 474 Plot* plot) { |
| 508 struct TimestampSize { | 475 struct TimestampSize { |
| 509 TimestampSize(uint64_t t, size_t s) : timestamp(t), size(s) {} | 476 TimestampSize(uint64_t t, size_t s) : timestamp(t), size(s) {} |
| 510 uint64_t timestamp; | 477 uint64_t timestamp; |
| 511 size_t size; | 478 size_t size; |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 524 if (direction == desired_direction) { | 491 if (direction == desired_direction) { |
| 525 uint64_t timestamp = parsed_log_.GetTimestamp(i); | 492 uint64_t timestamp = parsed_log_.GetTimestamp(i); |
| 526 packets.push_back(TimestampSize(timestamp, total_length)); | 493 packets.push_back(TimestampSize(timestamp, total_length)); |
| 527 } | 494 } |
| 528 } | 495 } |
| 529 } | 496 } |
| 530 | 497 |
| 531 size_t window_index_begin = 0; | 498 size_t window_index_begin = 0; |
| 532 size_t window_index_end = 0; | 499 size_t window_index_end = 0; |
| 533 size_t bytes_in_window = 0; | 500 size_t bytes_in_window = 0; |
| 534 float max_y = 0; | |
| 535 | 501 |
| 536 // Calculate a moving average of the bitrate and store in a TimeSeries. | 502 // Calculate a moving average of the bitrate and store in a TimeSeries. |
| 537 plot->series.push_back(TimeSeries()); | 503 plot->series_list_.push_back(TimeSeries()); |
| 538 for (uint64_t time = begin_time_; time < end_time_ + step_; time += step_) { | 504 for (uint64_t time = begin_time_; time < end_time_ + step_; time += step_) { |
| 539 while (window_index_end < packets.size() && | 505 while (window_index_end < packets.size() && |
| 540 packets[window_index_end].timestamp < time) { | 506 packets[window_index_end].timestamp < time) { |
| 541 bytes_in_window += packets[window_index_end].size; | 507 bytes_in_window += packets[window_index_end].size; |
| 542 window_index_end++; | 508 window_index_end++; |
| 543 } | 509 } |
| 544 while (window_index_begin < packets.size() && | 510 while (window_index_begin < packets.size() && |
| 545 packets[window_index_begin].timestamp < time - window_duration_) { | 511 packets[window_index_begin].timestamp < time - window_duration_) { |
| 546 RTC_DCHECK_LE(packets[window_index_begin].size, bytes_in_window); | 512 RTC_DCHECK_LE(packets[window_index_begin].size, bytes_in_window); |
| 547 bytes_in_window -= packets[window_index_begin].size; | 513 bytes_in_window -= packets[window_index_begin].size; |
| 548 window_index_begin++; | 514 window_index_begin++; |
| 549 } | 515 } |
| 550 float window_duration_in_seconds = | 516 float window_duration_in_seconds = |
| 551 static_cast<float>(window_duration_) / 1000000; | 517 static_cast<float>(window_duration_) / 1000000; |
| 552 float x = static_cast<float>(time - begin_time_) / 1000000; | 518 float x = static_cast<float>(time - begin_time_) / 1000000; |
| 553 float y = bytes_in_window * 8 / window_duration_in_seconds / 1000; | 519 float y = bytes_in_window * 8 / window_duration_in_seconds / 1000; |
| 554 max_y = std::max(max_y, y); | 520 plot->series_list_.back().points.push_back(TimeSeriesPoint(x, y)); |
| 555 plot->series.back().points.push_back(TimeSeriesPoint(x, y)); | |
| 556 } | 521 } |
| 557 | 522 |
| 558 // Set labels. | 523 // Set labels. |
| 559 if (desired_direction == webrtc::PacketDirection::kIncomingPacket) { | 524 if (desired_direction == webrtc::PacketDirection::kIncomingPacket) { |
| 560 plot->series.back().label = "Incoming bitrate"; | 525 plot->series_list_.back().label = "Incoming bitrate"; |
| 561 } else if (desired_direction == webrtc::PacketDirection::kOutgoingPacket) { | 526 } else if (desired_direction == webrtc::PacketDirection::kOutgoingPacket) { |
| 562 plot->series.back().label = "Outgoing bitrate"; | 527 plot->series_list_.back().label = "Outgoing bitrate"; |
| 563 } | 528 } |
| 564 plot->series.back().style = LINE_GRAPH; | 529 plot->series_list_.back().style = LINE_GRAPH; |
| 565 | 530 |
| 566 // Overlay the send-side bandwidth estimate over the outgoing bitrate. | 531 // Overlay the send-side bandwidth estimate over the outgoing bitrate. |
| 567 if (desired_direction == kOutgoingPacket) { | 532 if (desired_direction == kOutgoingPacket) { |
| 568 plot->series.push_back(TimeSeries()); | 533 plot->series_list_.push_back(TimeSeries()); |
| 569 for (auto& bwe_update : bwe_loss_updates_) { | 534 for (auto& bwe_update : bwe_loss_updates_) { |
| 570 float x = | 535 float x = |
| 571 static_cast<float>(bwe_update.timestamp - begin_time_) / 1000000; | 536 static_cast<float>(bwe_update.timestamp - begin_time_) / 1000000; |
| 572 float y = static_cast<float>(bwe_update.new_bitrate) / 1000; | 537 float y = static_cast<float>(bwe_update.new_bitrate) / 1000; |
| 573 max_y = std::max(max_y, y); | 538 plot->series_list_.back().points.emplace_back(x, y); |
| 574 plot->series.back().points.emplace_back(x, y); | |
| 575 } | 539 } |
| 576 plot->series.back().label = "Loss-based estimate"; | 540 plot->series_list_.back().label = "Loss-based estimate"; |
| 577 plot->series.back().style = LINE_GRAPH; | 541 plot->series_list_.back().style = LINE_GRAPH; |
| 578 } | 542 } |
| 579 | 543 plot->series_list_.back().style = LINE_GRAPH; |
| 580 plot->xaxis_min = kDefaultXMin; | 544 plot->SetXAxis(0, call_duration_s_, "Time (s)", kLeftMargin, kRightMargin); |
| 581 plot->xaxis_max = (end_time_ - begin_time_) / 1000000 * kXMargin; | 545 plot->SetSuggestedYAxis(0, 1, "Bitrate (kbps)", kBottomMargin, kTopMargin); |
| 582 plot->xaxis_label = "Time (s)"; | |
| 583 plot->yaxis_min = kDefaultYMin; | |
| 584 plot->yaxis_max = max_y * kYMargin; | |
| 585 plot->yaxis_label = "Bitrate (kbps)"; | |
| 586 if (desired_direction == webrtc::PacketDirection::kIncomingPacket) { | 546 if (desired_direction == webrtc::PacketDirection::kIncomingPacket) { |
| 587 plot->title = "Incoming RTP bitrate"; | 547 plot->SetTitle("Incoming RTP bitrate"); |
| 588 } else if (desired_direction == webrtc::PacketDirection::kOutgoingPacket) { | 548 } else if (desired_direction == webrtc::PacketDirection::kOutgoingPacket) { |
| 589 plot->title = "Outgoing RTP bitrate"; | 549 plot->SetTitle("Outgoing RTP bitrate"); |
| 590 } | 550 } |
| 591 } | 551 } |
| 592 | 552 |
| 593 // For each SSRC, plot the bandwidth used by that stream. | 553 // For each SSRC, plot the bandwidth used by that stream. |
| 594 void EventLogAnalyzer::CreateStreamBitrateGraph( | 554 void EventLogAnalyzer::CreateStreamBitrateGraph( |
| 595 PacketDirection desired_direction, | 555 PacketDirection desired_direction, |
| 596 Plot* plot) { | 556 Plot* plot) { |
| 597 struct TimestampSize { | 557 struct TimestampSize { |
| 598 TimestampSize(uint64_t t, size_t s) : timestamp(t), size(s) {} | 558 TimestampSize(uint64_t t, size_t s) : timestamp(t), size(s) {} |
| 599 uint64_t timestamp; | 559 uint64_t timestamp; |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 620 // Filter on SSRC. | 580 // Filter on SSRC. |
| 621 if (MatchingSsrc(parsed_header.ssrc, desired_ssrc_)) { | 581 if (MatchingSsrc(parsed_header.ssrc, desired_ssrc_)) { |
| 622 uint64_t timestamp = parsed_log_.GetTimestamp(i); | 582 uint64_t timestamp = parsed_log_.GetTimestamp(i); |
| 623 packets[parsed_header.ssrc].push_back( | 583 packets[parsed_header.ssrc].push_back( |
| 624 TimestampSize(timestamp, total_length)); | 584 TimestampSize(timestamp, total_length)); |
| 625 } | 585 } |
| 626 } | 586 } |
| 627 } | 587 } |
| 628 } | 588 } |
| 629 | 589 |
| 630 float max_y = 0; | |
| 631 | |
| 632 for (auto& kv : packets) { | 590 for (auto& kv : packets) { |
| 633 size_t window_index_begin = 0; | 591 size_t window_index_begin = 0; |
| 634 size_t window_index_end = 0; | 592 size_t window_index_end = 0; |
| 635 size_t bytes_in_window = 0; | 593 size_t bytes_in_window = 0; |
| 636 | 594 |
| 637 // Calculate a moving average of the bitrate and store in a TimeSeries. | 595 // Calculate a moving average of the bitrate and store in a TimeSeries. |
| 638 plot->series.push_back(TimeSeries()); | 596 plot->series_list_.push_back(TimeSeries()); |
| 639 for (uint64_t time = begin_time_; time < end_time_ + step_; time += step_) { | 597 for (uint64_t time = begin_time_; time < end_time_ + step_; time += step_) { |
| 640 while (window_index_end < kv.second.size() && | 598 while (window_index_end < kv.second.size() && |
| 641 kv.second[window_index_end].timestamp < time) { | 599 kv.second[window_index_end].timestamp < time) { |
| 642 bytes_in_window += kv.second[window_index_end].size; | 600 bytes_in_window += kv.second[window_index_end].size; |
| 643 window_index_end++; | 601 window_index_end++; |
| 644 } | 602 } |
| 645 while (window_index_begin < kv.second.size() && | 603 while (window_index_begin < kv.second.size() && |
| 646 kv.second[window_index_begin].timestamp < | 604 kv.second[window_index_begin].timestamp < |
| 647 time - window_duration_) { | 605 time - window_duration_) { |
| 648 RTC_DCHECK_LE(kv.second[window_index_begin].size, bytes_in_window); | 606 RTC_DCHECK_LE(kv.second[window_index_begin].size, bytes_in_window); |
| 649 bytes_in_window -= kv.second[window_index_begin].size; | 607 bytes_in_window -= kv.second[window_index_begin].size; |
| 650 window_index_begin++; | 608 window_index_begin++; |
| 651 } | 609 } |
| 652 float window_duration_in_seconds = | 610 float window_duration_in_seconds = |
| 653 static_cast<float>(window_duration_) / 1000000; | 611 static_cast<float>(window_duration_) / 1000000; |
| 654 float x = static_cast<float>(time - begin_time_) / 1000000; | 612 float x = static_cast<float>(time - begin_time_) / 1000000; |
| 655 float y = bytes_in_window * 8 / window_duration_in_seconds / 1000; | 613 float y = bytes_in_window * 8 / window_duration_in_seconds / 1000; |
| 656 max_y = std::max(max_y, y); | 614 plot->series_list_.back().points.push_back(TimeSeriesPoint(x, y)); |
| 657 plot->series.back().points.push_back(TimeSeriesPoint(x, y)); | |
| 658 } | 615 } |
| 659 | 616 |
| 660 // Set labels. | 617 // Set labels. |
| 661 plot->series.back().label = SsrcToString(kv.first); | 618 plot->series_list_.back().label = SsrcToString(kv.first); |
| 662 plot->series.back().style = LINE_GRAPH; | 619 plot->series_list_.back().style = LINE_GRAPH; |
| 663 } | 620 } |
| 664 | 621 |
| 665 plot->xaxis_min = kDefaultXMin; | 622 plot->SetXAxis(0, call_duration_s_, "Time (s)", kLeftMargin, kRightMargin); |
| 666 plot->xaxis_max = (end_time_ - begin_time_) / 1000000 * kXMargin; | 623 plot->SetSuggestedYAxis(0, 1, "Bitrate (kbps)", kBottomMargin, kTopMargin); |
| 667 plot->xaxis_label = "Time (s)"; | |
| 668 plot->yaxis_min = kDefaultYMin; | |
| 669 plot->yaxis_max = max_y * kYMargin; | |
| 670 plot->yaxis_label = "Bitrate (kbps)"; | |
| 671 if (desired_direction == webrtc::PacketDirection::kIncomingPacket) { | 624 if (desired_direction == webrtc::PacketDirection::kIncomingPacket) { |
| 672 plot->title = "Incoming bitrate per stream"; | 625 plot->SetTitle("Incoming bitrate per stream"); |
| 673 } else if (desired_direction == webrtc::PacketDirection::kOutgoingPacket) { | 626 } else if (desired_direction == webrtc::PacketDirection::kOutgoingPacket) { |
| 674 plot->title = "Outgoing bitrate per stream"; | 627 plot->SetTitle("Outgoing bitrate per stream"); |
| 675 } | 628 } |
| 676 } | 629 } |
| 677 | 630 |
| 678 } // namespace plotting | 631 } // namespace plotting |
| 679 } // namespace webrtc | 632 } // namespace webrtc |
| OLD | NEW |