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