| 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 58 matching lines...) Expand 10 before | Expand all | Expand 10 after  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 class StreamId { |  | 
| 80  public: |  | 
| 81   StreamId(uint32_t ssrc, |  | 
| 82            webrtc::PacketDirection direction, |  | 
| 83            webrtc::MediaType media_type) |  | 
| 84       : ssrc_(ssrc), direction_(direction), media_type_(media_type) {} |  | 
| 85 |  | 
| 86   bool operator<(const StreamId& other) const { |  | 
| 87     if (ssrc_ < other.ssrc_) { |  | 
| 88       return true; |  | 
| 89     } |  | 
| 90     if (ssrc_ == other.ssrc_) { |  | 
| 91       if (media_type_ < other.media_type_) { |  | 
| 92         return true; |  | 
| 93       } |  | 
| 94       if (media_type_ == other.media_type_) { |  | 
| 95         if (direction_ < other.direction_) { |  | 
| 96           return true; |  | 
| 97         } |  | 
| 98       } |  | 
| 99     } |  | 
| 100     return false; |  | 
| 101   } |  | 
| 102 |  | 
| 103   bool operator==(const StreamId& other) const { |  | 
| 104     return ssrc_ == other.ssrc_ && direction_ == other.direction_ && |  | 
| 105            media_type_ == other.media_type_; |  | 
| 106   } |  | 
| 107 |  | 
| 108   uint32_t GetSsrc() const { return ssrc_; } |  | 
| 109 |  | 
| 110  private: |  | 
| 111   uint32_t ssrc_; |  | 
| 112   webrtc::PacketDirection direction_; |  | 
| 113   webrtc::MediaType media_type_; |  | 
| 114 }; |  | 
| 115 |  | 
| 116 const double kXMargin = 1.02; | 79 const double kXMargin = 1.02; | 
| 117 const double kYMargin = 1.1; | 80 const double kYMargin = 1.1; | 
| 118 const double kDefaultXMin = -1; | 81 const double kDefaultXMin = -1; | 
| 119 const double kDefaultYMin = -1; | 82 const double kDefaultYMin = -1; | 
| 120 | 83 | 
| 121 }  // namespace | 84 }  // namespace | 
| 122 | 85 | 
| 123 namespace webrtc { | 86 namespace webrtc { | 
| 124 namespace plotting { | 87 namespace plotting { | 
| 125 | 88 | 
|  | 89 | 
|  | 90 bool EventLogAnalyzer::StreamId::operator<(const StreamId& other) const { | 
|  | 91   if (ssrc_ < other.ssrc_) { | 
|  | 92     return true; | 
|  | 93   } | 
|  | 94   if (ssrc_ == other.ssrc_) { | 
|  | 95     if (media_type_ < other.media_type_) { | 
|  | 96       return true; | 
|  | 97     } | 
|  | 98     if (media_type_ == other.media_type_) { | 
|  | 99       if (direction_ < other.direction_) { | 
|  | 100         return true; | 
|  | 101       } | 
|  | 102     } | 
|  | 103   } | 
|  | 104   return false; | 
|  | 105 } | 
|  | 106 | 
|  | 107 bool EventLogAnalyzer::StreamId::operator==(const StreamId& other) const { | 
|  | 108   return ssrc_ == other.ssrc_ && direction_ == other.direction_ && | 
|  | 109          media_type_ == other.media_type_; | 
|  | 110 } | 
|  | 111 | 
|  | 112 | 
| 126 EventLogAnalyzer::EventLogAnalyzer(const ParsedRtcEventLog& log) | 113 EventLogAnalyzer::EventLogAnalyzer(const ParsedRtcEventLog& log) | 
| 127     : parsed_log_(log), window_duration_(250000), step_(10000) { | 114     : parsed_log_(log), window_duration_(250000), step_(10000) { | 
| 128   uint64_t first_timestamp = std::numeric_limits<uint64_t>::max(); | 115   uint64_t first_timestamp = std::numeric_limits<uint64_t>::max(); | 
| 129   uint64_t last_timestamp = std::numeric_limits<uint64_t>::min(); | 116   uint64_t last_timestamp = std::numeric_limits<uint64_t>::min(); | 
|  | 117 | 
|  | 118   // Maps a stream identifier consisting of ssrc, direction and MediaType | 
|  | 119   // to the header extensions used by that stream, | 
|  | 120   std::map<StreamId, RtpHeaderExtensionMap> extension_maps; | 
|  | 121 | 
|  | 122   PacketDirection direction; | 
|  | 123   MediaType media_type; | 
|  | 124   uint8_t header[IP_PACKET_SIZE]; | 
|  | 125   size_t header_length; | 
|  | 126   size_t total_length; | 
|  | 127 | 
| 130   for (size_t i = 0; i < parsed_log_.GetNumberOfEvents(); i++) { | 128   for (size_t i = 0; i < parsed_log_.GetNumberOfEvents(); i++) { | 
| 131     ParsedRtcEventLog::EventType event_type = parsed_log_.GetEventType(i); | 129     ParsedRtcEventLog::EventType event_type = parsed_log_.GetEventType(i); | 
| 132     if (event_type == ParsedRtcEventLog::EventType::VIDEO_RECEIVER_CONFIG_EVENT) | 130     if (event_type != ParsedRtcEventLog::VIDEO_RECEIVER_CONFIG_EVENT && | 
| 133       continue; | 131         event_type != ParsedRtcEventLog::VIDEO_SENDER_CONFIG_EVENT && | 
| 134     if (event_type == ParsedRtcEventLog::EventType::VIDEO_SENDER_CONFIG_EVENT) | 132         event_type != ParsedRtcEventLog::AUDIO_RECEIVER_CONFIG_EVENT && | 
| 135       continue; | 133         event_type != ParsedRtcEventLog::AUDIO_SENDER_CONFIG_EVENT) { | 
| 136     if (event_type == ParsedRtcEventLog::EventType::AUDIO_RECEIVER_CONFIG_EVENT) | 134       uint64_t timestamp = parsed_log_.GetTimestamp(i); | 
| 137       continue; | 135       first_timestamp = std::min(first_timestamp, timestamp); | 
| 138     if (event_type == ParsedRtcEventLog::EventType::AUDIO_SENDER_CONFIG_EVENT) | 136       last_timestamp = std::max(last_timestamp, timestamp); | 
| 139       continue; | 137     } | 
| 140     uint64_t timestamp = parsed_log_.GetTimestamp(i); | 138 | 
| 141     first_timestamp = std::min(first_timestamp, timestamp); | 139     switch (parsed_log_.GetEventType(i)) { | 
| 142     last_timestamp = std::max(last_timestamp, timestamp); | 140       case ParsedRtcEventLog::VIDEO_RECEIVER_CONFIG_EVENT: { | 
|  | 141         VideoReceiveStream::Config config(nullptr); | 
|  | 142         parsed_log_.GetVideoReceiveConfig(i, &config); | 
|  | 143         StreamId stream(config.rtp.remote_ssrc, kIncomingPacket, | 
|  | 144                         MediaType::VIDEO); | 
|  | 145         extension_maps[stream].Erase(); | 
|  | 146         for (size_t j = 0; j < config.rtp.extensions.size(); ++j) { | 
|  | 147           const std::string& extension = config.rtp.extensions[j].uri; | 
|  | 148           int id = config.rtp.extensions[j].id; | 
|  | 149           extension_maps[stream].Register(StringToRtpExtensionType(extension), | 
|  | 150                                           id); | 
|  | 151         } | 
|  | 152         break; | 
|  | 153       } | 
|  | 154       case ParsedRtcEventLog::VIDEO_SENDER_CONFIG_EVENT: { | 
|  | 155         VideoSendStream::Config config(nullptr); | 
|  | 156         parsed_log_.GetVideoSendConfig(i, &config); | 
|  | 157         for (auto ssrc : config.rtp.ssrcs) { | 
|  | 158           StreamId stream(ssrc, kOutgoingPacket, MediaType::VIDEO); | 
|  | 159           extension_maps[stream].Erase(); | 
|  | 160           for (size_t j = 0; j < config.rtp.extensions.size(); ++j) { | 
|  | 161             const std::string& extension = config.rtp.extensions[j].uri; | 
|  | 162             int id = config.rtp.extensions[j].id; | 
|  | 163             extension_maps[stream].Register(StringToRtpExtensionType(extension), | 
|  | 164                                             id); | 
|  | 165           } | 
|  | 166         } | 
|  | 167         break; | 
|  | 168       } | 
|  | 169       case ParsedRtcEventLog::AUDIO_RECEIVER_CONFIG_EVENT: { | 
|  | 170         AudioReceiveStream::Config config; | 
|  | 171         // TODO(terelius): Parse the audio configs once we have them. | 
|  | 172         break; | 
|  | 173       } | 
|  | 174       case ParsedRtcEventLog::AUDIO_SENDER_CONFIG_EVENT: { | 
|  | 175         AudioSendStream::Config config(nullptr); | 
|  | 176         // TODO(terelius): Parse the audio configs once we have them. | 
|  | 177         break; | 
|  | 178       } | 
|  | 179       case ParsedRtcEventLog::RTP_EVENT: { | 
|  | 180         parsed_log_.GetRtpHeader(i, &direction, &media_type, header, | 
|  | 181                                  &header_length, &total_length); | 
|  | 182         // Parse header to get SSRC. | 
|  | 183         RtpUtility::RtpHeaderParser rtp_parser(header, header_length); | 
|  | 184         RTPHeader parsed_header; | 
|  | 185         rtp_parser.Parse(&parsed_header); | 
|  | 186         StreamId stream(parsed_header.ssrc, direction, media_type); | 
|  | 187         // Look up the extension_map and parse it again to get the extensions. | 
|  | 188         if (extension_maps.count(stream) == 1) { | 
|  | 189           RtpHeaderExtensionMap* extension_map = &extension_maps[stream]; | 
|  | 190           rtp_parser.Parse(&parsed_header, extension_map); | 
|  | 191         } | 
|  | 192         uint64_t timestamp = parsed_log_.GetTimestamp(i); | 
|  | 193         rtp_packets_[stream].push_back( | 
|  | 194             LoggedRtpPacket(timestamp, parsed_header)); | 
|  | 195         break; | 
|  | 196       } | 
|  | 197       case ParsedRtcEventLog::RTCP_EVENT: { | 
|  | 198         break; | 
|  | 199       } | 
|  | 200       case ParsedRtcEventLog::LOG_START: { | 
|  | 201         break; | 
|  | 202       } | 
|  | 203       case ParsedRtcEventLog::LOG_END: { | 
|  | 204         break; | 
|  | 205       } | 
|  | 206       case ParsedRtcEventLog::BWE_PACKET_LOSS_EVENT: { | 
|  | 207         break; | 
|  | 208       } | 
|  | 209       case ParsedRtcEventLog::BWE_PACKET_DELAY_EVENT: { | 
|  | 210         break; | 
|  | 211       } | 
|  | 212       case ParsedRtcEventLog::AUDIO_PLAYOUT_EVENT: { | 
|  | 213         break; | 
|  | 214       } | 
|  | 215       case ParsedRtcEventLog::UNKNOWN_EVENT: { | 
|  | 216         break; | 
|  | 217       } | 
|  | 218     } | 
| 143   } | 219   } | 
|  | 220 | 
| 144   if (last_timestamp < first_timestamp) { | 221   if (last_timestamp < first_timestamp) { | 
| 145     // No useful events in the log. | 222     // No useful events in the log. | 
| 146     first_timestamp = last_timestamp = 0; | 223     first_timestamp = last_timestamp = 0; | 
| 147   } | 224   } | 
| 148   begin_time_ = first_timestamp; | 225   begin_time_ = first_timestamp; | 
| 149   end_time_ = last_timestamp; | 226   end_time_ = last_timestamp; | 
| 150 } | 227 } | 
| 151 | 228 | 
| 152 void EventLogAnalyzer::CreatePacketGraph(PacketDirection desired_direction, | 229 void EventLogAnalyzer::CreatePacketGraph(PacketDirection desired_direction, | 
| 153                                          Plot* plot) { | 230                                          Plot* plot) { | 
| (...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 300   plot->xaxis_min = kDefaultXMin; | 377   plot->xaxis_min = kDefaultXMin; | 
| 301   plot->xaxis_max = (end_time_ - begin_time_) / 1000000 * kXMargin; | 378   plot->xaxis_max = (end_time_ - begin_time_) / 1000000 * kXMargin; | 
| 302   plot->xaxis_label = "Time (s)"; | 379   plot->xaxis_label = "Time (s)"; | 
| 303   plot->yaxis_min = min_y - (kYMargin - 1) / 2 * (max_y - min_y); | 380   plot->yaxis_min = min_y - (kYMargin - 1) / 2 * (max_y - min_y); | 
| 304   plot->yaxis_max = max_y + (kYMargin - 1) / 2 * (max_y - min_y); | 381   plot->yaxis_max = max_y + (kYMargin - 1) / 2 * (max_y - min_y); | 
| 305   plot->yaxis_label = "Difference since last packet"; | 382   plot->yaxis_label = "Difference since last packet"; | 
| 306   plot->title = "Sequence number"; | 383   plot->title = "Sequence number"; | 
| 307 } | 384 } | 
| 308 | 385 | 
| 309 void EventLogAnalyzer::CreateDelayChangeGraph(Plot* plot) { | 386 void EventLogAnalyzer::CreateDelayChangeGraph(Plot* plot) { | 
| 310   // Maps a stream identifier consisting of ssrc, direction and MediaType |  | 
| 311   // to the header extensions used by that stream, |  | 
| 312   std::map<StreamId, RtpHeaderExtensionMap> extension_maps; |  | 
| 313 |  | 
| 314   struct SendReceiveTime { |  | 
| 315     SendReceiveTime() = default; |  | 
| 316     SendReceiveTime(uint32_t send_time, uint64_t recv_time) |  | 
| 317         : absolute_send_time(send_time), receive_timestamp(recv_time) {} |  | 
| 318     uint32_t absolute_send_time;  // 24-bit value in units of 2^-18 seconds. |  | 
| 319     uint64_t receive_timestamp;   // In microseconds. |  | 
| 320   }; |  | 
| 321   std::map<StreamId, SendReceiveTime> last_packet; |  | 
| 322   std::map<StreamId, TimeSeries> time_series; |  | 
| 323 |  | 
| 324   PacketDirection direction; |  | 
| 325   MediaType media_type; |  | 
| 326   uint8_t header[IP_PACKET_SIZE]; |  | 
| 327   size_t header_length, total_length; |  | 
| 328 |  | 
| 329   double max_y = 10; | 387   double max_y = 10; | 
| 330   double min_y = 0; | 388   double min_y = 0; | 
| 331 | 389 | 
| 332   for (size_t i = 0; i < parsed_log_.GetNumberOfEvents(); i++) { | 390   for (auto& kv : rtp_packets_) { | 
| 333     ParsedRtcEventLog::EventType event_type = parsed_log_.GetEventType(i); | 391     StreamId stream_id = kv.first; | 
| 334     if (event_type == ParsedRtcEventLog::VIDEO_RECEIVER_CONFIG_EVENT) { | 392     // Filter on direction and SSRC. | 
| 335       VideoReceiveStream::Config config(nullptr); | 393     if (stream_id.GetDirection() != kIncomingPacket || | 
| 336       parsed_log_.GetVideoReceiveConfig(i, &config); | 394         !MatchingSsrc(stream_id.GetSsrc(), desired_ssrc_)) { | 
| 337       StreamId stream(config.rtp.remote_ssrc, kIncomingPacket, | 395       continue; | 
| 338                       MediaType::VIDEO); | 396     } | 
| 339       extension_maps[stream].Erase(); | 397 | 
| 340       for (size_t j = 0; j < config.rtp.extensions.size(); ++j) { | 398     TimeSeries time_series; | 
| 341         const std::string& extension = config.rtp.extensions[j].uri; | 399     time_series.label = SsrcToString(stream_id.GetSsrc()); | 
| 342         int id = config.rtp.extensions[j].id; | 400     time_series.style = BAR_GRAPH; | 
| 343         extension_maps[stream].Register(StringToRtpExtensionType(extension), | 401     const std::vector<LoggedRtpPacket>& packet_stream = kv.second; | 
| 344                                         id); | 402     int64_t last_abs_send_time = 0; | 
| 345       } | 403     int64_t last_timestamp = 0; | 
| 346     } else if (event_type == ParsedRtcEventLog::VIDEO_SENDER_CONFIG_EVENT) { | 404     for (const LoggedRtpPacket& packet : packet_stream) { | 
| 347       VideoSendStream::Config config(nullptr); | 405       if (packet.header.extension.hasAbsoluteSendTime) { | 
| 348       parsed_log_.GetVideoSendConfig(i, &config); | 406         int64_t send_time_diff = | 
| 349       for (auto ssrc : config.rtp.ssrcs) { | 407             WrappingDifference(packet.header.extension.absoluteSendTime, | 
| 350         StreamId stream(ssrc, kIncomingPacket, MediaType::VIDEO); | 408                                last_abs_send_time, 1ul << 24); | 
| 351         extension_maps[stream].Erase(); | 409         int64_t recv_time_diff = packet.timestamp - last_timestamp; | 
| 352         for (size_t j = 0; j < config.rtp.extensions.size(); ++j) { | 410 | 
| 353           const std::string& extension = config.rtp.extensions[j].uri; | 411         last_abs_send_time = packet.header.extension.absoluteSendTime; | 
| 354           int id = config.rtp.extensions[j].id; | 412         last_timestamp = packet.timestamp; | 
| 355           extension_maps[stream].Register(StringToRtpExtensionType(extension), | 413 | 
| 356                                           id); | 414         float x = static_cast<float>(packet.timestamp - begin_time_) / 1000000; | 
|  | 415         double y = | 
|  | 416             static_cast<double>(recv_time_diff - | 
|  | 417                                 AbsSendTimeToMicroseconds(send_time_diff)) / | 
|  | 418             1000; | 
|  | 419         if (time_series.points.size() == 0) { | 
|  | 420           // There were no previously logged packets for this SSRC. | 
|  | 421           // Generate a point, but place it on the x-axis. | 
|  | 422           y = 0; | 
| 357         } | 423         } | 
| 358       } | 424         max_y = std::max(max_y, y); | 
| 359     } else if (event_type == ParsedRtcEventLog::AUDIO_RECEIVER_CONFIG_EVENT) { | 425         min_y = std::min(min_y, y); | 
| 360       AudioReceiveStream::Config config; | 426         time_series.points.emplace_back(x, y); | 
| 361       // TODO(terelius): Parse the audio configs once we have them |  | 
| 362     } else if (event_type == ParsedRtcEventLog::AUDIO_SENDER_CONFIG_EVENT) { |  | 
| 363       AudioSendStream::Config config(nullptr); |  | 
| 364       // TODO(terelius): Parse the audio configs once we have them |  | 
| 365     } else if (event_type == ParsedRtcEventLog::RTP_EVENT) { |  | 
| 366       parsed_log_.GetRtpHeader(i, &direction, &media_type, header, |  | 
| 367                                &header_length, &total_length); |  | 
| 368       if (direction == kIncomingPacket) { |  | 
| 369         // Parse header to get SSRC. |  | 
| 370         RtpUtility::RtpHeaderParser rtp_parser(header, header_length); |  | 
| 371         RTPHeader parsed_header; |  | 
| 372         rtp_parser.Parse(&parsed_header); |  | 
| 373         // Filter on SSRC. |  | 
| 374         if (MatchingSsrc(parsed_header.ssrc, desired_ssrc_)) { |  | 
| 375           StreamId stream(parsed_header.ssrc, direction, media_type); |  | 
| 376           // Look up the extension_map and parse it again to get the extensions. |  | 
| 377           if (extension_maps.count(stream) == 1) { |  | 
| 378             RtpHeaderExtensionMap* extension_map = &extension_maps[stream]; |  | 
| 379             rtp_parser.Parse(&parsed_header, extension_map); |  | 
| 380             if (parsed_header.extension.hasAbsoluteSendTime) { |  | 
| 381               uint64_t timestamp = parsed_log_.GetTimestamp(i); |  | 
| 382               int64_t send_time_diff = WrappingDifference( |  | 
| 383                   parsed_header.extension.absoluteSendTime, |  | 
| 384                   last_packet[stream].absolute_send_time, 1ul << 24); |  | 
| 385               int64_t recv_time_diff = |  | 
| 386                   timestamp - last_packet[stream].receive_timestamp; |  | 
| 387 |  | 
| 388               float x = static_cast<float>(timestamp - begin_time_) / 1000000; |  | 
| 389               double y = static_cast<double>( |  | 
| 390                              recv_time_diff - |  | 
| 391                              AbsSendTimeToMicroseconds(send_time_diff)) / |  | 
| 392                          1000; |  | 
| 393               if (time_series[stream].points.size() == 0) { |  | 
| 394                 // There were no previusly logged playout for this SSRC. |  | 
| 395                 // Generate a point, but place it on the x-axis. |  | 
| 396                 y = 0; |  | 
| 397               } |  | 
| 398               max_y = std::max(max_y, y); |  | 
| 399               min_y = std::min(min_y, y); |  | 
| 400               time_series[stream].points.push_back(TimeSeriesPoint(x, y)); |  | 
| 401               last_packet[stream] = SendReceiveTime( |  | 
| 402                   parsed_header.extension.absoluteSendTime, timestamp); |  | 
| 403             } |  | 
| 404           } |  | 
| 405         } |  | 
| 406       } | 427       } | 
| 407     } | 428     } | 
| 408   } | 429     // Add the data set to the plot. | 
| 409 | 430     plot->series.push_back(std::move(time_series)); | 
| 410   // Set labels and put in graph. |  | 
| 411   for (auto& kv : time_series) { |  | 
| 412     kv.second.label = SsrcToString(kv.first.GetSsrc()); |  | 
| 413     kv.second.style = BAR_GRAPH; |  | 
| 414     plot->series.push_back(std::move(kv.second)); |  | 
| 415   } | 431   } | 
| 416 | 432 | 
| 417   plot->xaxis_min = kDefaultXMin; | 433   plot->xaxis_min = kDefaultXMin; | 
| 418   plot->xaxis_max = (end_time_ - begin_time_) / 1000000 * kXMargin; | 434   plot->xaxis_max = (end_time_ - begin_time_) / 1000000 * kXMargin; | 
| 419   plot->xaxis_label = "Time (s)"; | 435   plot->xaxis_label = "Time (s)"; | 
| 420   plot->yaxis_min = min_y - (kYMargin - 1) / 2 * (max_y - min_y); | 436   plot->yaxis_min = min_y - (kYMargin - 1) / 2 * (max_y - min_y); | 
| 421   plot->yaxis_max = max_y + (kYMargin - 1) / 2 * (max_y - min_y); | 437   plot->yaxis_max = max_y + (kYMargin - 1) / 2 * (max_y - min_y); | 
| 422   plot->yaxis_label = "Latency change (ms)"; | 438   plot->yaxis_label = "Latency change (ms)"; | 
| 423   plot->title = "Network latency change between consecutive packets"; | 439   plot->title = "Network latency change between consecutive packets"; | 
| 424 } | 440 } | 
| 425 | 441 | 
| 426 void EventLogAnalyzer::CreateAccumulatedDelayChangeGraph(Plot* plot) { | 442 void EventLogAnalyzer::CreateAccumulatedDelayChangeGraph(Plot* plot) { | 
| 427   // TODO(terelius): Refactor |  | 
| 428 |  | 
| 429   // Maps a stream identifier consisting of ssrc, direction and MediaType |  | 
| 430   // to the header extensions used by that stream. |  | 
| 431   std::map<StreamId, RtpHeaderExtensionMap> extension_maps; |  | 
| 432 |  | 
| 433   struct SendReceiveTime { |  | 
| 434     SendReceiveTime() = default; |  | 
| 435     SendReceiveTime(uint32_t send_time, uint64_t recv_time, double accumulated) |  | 
| 436         : absolute_send_time(send_time), |  | 
| 437           receive_timestamp(recv_time), |  | 
| 438           accumulated_delay(accumulated) {} |  | 
| 439     uint32_t absolute_send_time;  // 24-bit value in units of 2^-18 seconds. |  | 
| 440     uint64_t receive_timestamp;   // In microseconds. |  | 
| 441     double accumulated_delay;     // In milliseconds. |  | 
| 442   }; |  | 
| 443   std::map<StreamId, SendReceiveTime> last_packet; |  | 
| 444   std::map<StreamId, TimeSeries> time_series; |  | 
| 445 |  | 
| 446   PacketDirection direction; |  | 
| 447   MediaType media_type; |  | 
| 448   uint8_t header[IP_PACKET_SIZE]; |  | 
| 449   size_t header_length, total_length; |  | 
| 450 |  | 
| 451   double max_y = 10; | 443   double max_y = 10; | 
| 452   double min_y = 0; | 444   double min_y = 0; | 
| 453 | 445 | 
| 454   for (size_t i = 0; i < parsed_log_.GetNumberOfEvents(); i++) { | 446   for (auto& kv : rtp_packets_) { | 
| 455     ParsedRtcEventLog::EventType event_type = parsed_log_.GetEventType(i); | 447     StreamId stream_id = kv.first; | 
| 456     if (event_type == ParsedRtcEventLog::VIDEO_RECEIVER_CONFIG_EVENT) { | 448     // Filter on direction and SSRC. | 
| 457       VideoReceiveStream::Config config(nullptr); | 449     if (stream_id.GetDirection() != kIncomingPacket || | 
| 458       parsed_log_.GetVideoReceiveConfig(i, &config); | 450         !MatchingSsrc(stream_id.GetSsrc(), desired_ssrc_)) { | 
| 459       StreamId stream(config.rtp.remote_ssrc, kIncomingPacket, | 451       continue; | 
| 460                       MediaType::VIDEO); | 452     } | 
| 461       extension_maps[stream].Erase(); | 453     TimeSeries time_series; | 
| 462       for (size_t j = 0; j < config.rtp.extensions.size(); ++j) { | 454     time_series.label = SsrcToString(stream_id.GetSsrc()); | 
| 463         const std::string& extension = config.rtp.extensions[j].uri; | 455     time_series.style = LINE_GRAPH; | 
| 464         int id = config.rtp.extensions[j].id; | 456     const std::vector<LoggedRtpPacket>& packet_stream = kv.second; | 
| 465         extension_maps[stream].Register(StringToRtpExtensionType(extension), | 457     int64_t last_abs_send_time = 0; | 
| 466                                         id); | 458     int64_t last_timestamp = 0; | 
| 467       } | 459     double accumulated_delay_ms = 0; | 
| 468     } else if (event_type == ParsedRtcEventLog::VIDEO_SENDER_CONFIG_EVENT) { | 460     for (const LoggedRtpPacket& packet : packet_stream) { | 
| 469       VideoSendStream::Config config(nullptr); | 461       if (packet.header.extension.hasAbsoluteSendTime) { | 
| 470       parsed_log_.GetVideoSendConfig(i, &config); | 462         int64_t send_time_diff = | 
| 471       for (auto ssrc : config.rtp.ssrcs) { | 463             WrappingDifference(packet.header.extension.absoluteSendTime, | 
| 472         StreamId stream(ssrc, kIncomingPacket, MediaType::VIDEO); | 464                                last_abs_send_time, 1ul << 24); | 
| 473         extension_maps[stream].Erase(); | 465         int64_t recv_time_diff = packet.timestamp - last_timestamp; | 
| 474         for (size_t j = 0; j < config.rtp.extensions.size(); ++j) { | 466 | 
| 475           const std::string& extension = config.rtp.extensions[j].uri; | 467         last_abs_send_time = packet.header.extension.absoluteSendTime; | 
| 476           int id = config.rtp.extensions[j].id; | 468         last_timestamp = packet.timestamp; | 
| 477           extension_maps[stream].Register(StringToRtpExtensionType(extension), | 469 | 
| 478                                           id); | 470         float x = static_cast<float>(packet.timestamp - begin_time_) / 1000000; | 
|  | 471         accumulated_delay_ms += | 
|  | 472             static_cast<double>(recv_time_diff - | 
|  | 473                                 AbsSendTimeToMicroseconds(send_time_diff)) / | 
|  | 474             1000; | 
|  | 475         if (time_series.points.size() == 0) { | 
|  | 476           // There were no previously logged packets for this SSRC. | 
|  | 477           // Generate a point, but place it on the x-axis. | 
|  | 478           accumulated_delay_ms = 0; | 
| 479         } | 479         } | 
| 480       } | 480         max_y = std::max(max_y, accumulated_delay_ms); | 
| 481     } else if (event_type == ParsedRtcEventLog::AUDIO_RECEIVER_CONFIG_EVENT) { | 481         min_y = std::min(min_y, accumulated_delay_ms); | 
| 482       AudioReceiveStream::Config config; | 482         time_series.points.emplace_back(x, accumulated_delay_ms); | 
| 483       // TODO(terelius): Parse the audio configs once we have them |  | 
| 484     } else if (event_type == ParsedRtcEventLog::AUDIO_SENDER_CONFIG_EVENT) { |  | 
| 485       AudioSendStream::Config config(nullptr); |  | 
| 486       // TODO(terelius): Parse the audio configs once we have them |  | 
| 487     } else if (event_type == ParsedRtcEventLog::RTP_EVENT) { |  | 
| 488       parsed_log_.GetRtpHeader(i, &direction, &media_type, header, |  | 
| 489                                &header_length, &total_length); |  | 
| 490       if (direction == kIncomingPacket) { |  | 
| 491         // Parse header to get SSRC. |  | 
| 492         RtpUtility::RtpHeaderParser rtp_parser(header, header_length); |  | 
| 493         RTPHeader parsed_header; |  | 
| 494         rtp_parser.Parse(&parsed_header); |  | 
| 495         // Filter on SSRC. |  | 
| 496         if (MatchingSsrc(parsed_header.ssrc, desired_ssrc_)) { |  | 
| 497           StreamId stream(parsed_header.ssrc, direction, media_type); |  | 
| 498           // Look up the extension_map and parse it again to get the extensions. |  | 
| 499           if (extension_maps.count(stream) == 1) { |  | 
| 500             RtpHeaderExtensionMap* extension_map = &extension_maps[stream]; |  | 
| 501             rtp_parser.Parse(&parsed_header, extension_map); |  | 
| 502             if (parsed_header.extension.hasAbsoluteSendTime) { |  | 
| 503               uint64_t timestamp = parsed_log_.GetTimestamp(i); |  | 
| 504               int64_t send_time_diff = WrappingDifference( |  | 
| 505                   parsed_header.extension.absoluteSendTime, |  | 
| 506                   last_packet[stream].absolute_send_time, 1ul << 24); |  | 
| 507               int64_t recv_time_diff = |  | 
| 508                   timestamp - last_packet[stream].receive_timestamp; |  | 
| 509 |  | 
| 510               float x = static_cast<float>(timestamp - begin_time_) / 1000000; |  | 
| 511               double y = last_packet[stream].accumulated_delay + |  | 
| 512                          static_cast<double>( |  | 
| 513                              recv_time_diff - |  | 
| 514                              AbsSendTimeToMicroseconds(send_time_diff)) / |  | 
| 515                              1000; |  | 
| 516               if (time_series[stream].points.size() == 0) { |  | 
| 517                 // There were no previusly logged playout for this SSRC. |  | 
| 518                 // Generate a point, but place it on the x-axis. |  | 
| 519                 y = 0; |  | 
| 520               } |  | 
| 521               max_y = std::max(max_y, y); |  | 
| 522               min_y = std::min(min_y, y); |  | 
| 523               time_series[stream].points.push_back(TimeSeriesPoint(x, y)); |  | 
| 524               last_packet[stream] = SendReceiveTime( |  | 
| 525                   parsed_header.extension.absoluteSendTime, timestamp, y); |  | 
| 526             } |  | 
| 527           } |  | 
| 528         } |  | 
| 529       } | 483       } | 
| 530     } | 484     } | 
| 531   } | 485     // Add the data set to the plot. | 
| 532 | 486     plot->series.push_back(std::move(time_series)); | 
| 533   // Set labels and put in graph. |  | 
| 534   for (auto& kv : time_series) { |  | 
| 535     kv.second.label = SsrcToString(kv.first.GetSsrc()); |  | 
| 536     kv.second.style = LINE_GRAPH; |  | 
| 537     plot->series.push_back(std::move(kv.second)); |  | 
| 538   } | 487   } | 
| 539 | 488 | 
| 540   plot->xaxis_min = kDefaultXMin; | 489   plot->xaxis_min = kDefaultXMin; | 
| 541   plot->xaxis_max = (end_time_ - begin_time_) / 1000000 * kXMargin; | 490   plot->xaxis_max = (end_time_ - begin_time_) / 1000000 * kXMargin; | 
| 542   plot->xaxis_label = "Time (s)"; | 491   plot->xaxis_label = "Time (s)"; | 
| 543   plot->yaxis_min = min_y - (kYMargin - 1) / 2 * (max_y - min_y); | 492   plot->yaxis_min = min_y - (kYMargin - 1) / 2 * (max_y - min_y); | 
| 544   plot->yaxis_max = max_y + (kYMargin - 1) / 2 * (max_y - min_y); | 493   plot->yaxis_max = max_y + (kYMargin - 1) / 2 * (max_y - min_y); | 
| 545   plot->yaxis_label = "Latency change (ms)"; | 494   plot->yaxis_label = "Latency change (ms)"; | 
| 546   plot->title = "Accumulated network latency change"; | 495   plot->title = "Accumulated network latency change"; | 
| 547 } | 496 } | 
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 623 | 572 | 
| 624 // For each SSRC, plot the bandwidth used by that stream. | 573 // For each SSRC, plot the bandwidth used by that stream. | 
| 625 void EventLogAnalyzer::CreateStreamBitrateGraph( | 574 void EventLogAnalyzer::CreateStreamBitrateGraph( | 
| 626     PacketDirection desired_direction, | 575     PacketDirection desired_direction, | 
| 627     Plot* plot) { | 576     Plot* plot) { | 
| 628   struct TimestampSize { | 577   struct TimestampSize { | 
| 629     TimestampSize(uint64_t t, size_t s) : timestamp(t), size(s) {} | 578     TimestampSize(uint64_t t, size_t s) : timestamp(t), size(s) {} | 
| 630     uint64_t timestamp; | 579     uint64_t timestamp; | 
| 631     size_t size; | 580     size_t size; | 
| 632   }; | 581   }; | 
| 633   std::map<uint32_t, std::vector<TimestampSize> > packets; | 582   std::map<uint32_t, std::vector<TimestampSize>> packets; | 
| 634 | 583 | 
| 635   PacketDirection direction; | 584   PacketDirection direction; | 
| 636   MediaType media_type; | 585   MediaType media_type; | 
| 637   uint8_t header[IP_PACKET_SIZE]; | 586   uint8_t header[IP_PACKET_SIZE]; | 
| 638   size_t header_length, total_length; | 587   size_t header_length, total_length; | 
| 639 | 588 | 
| 640   // Extract timestamps and sizes for the relevant packets. | 589   // Extract timestamps and sizes for the relevant packets. | 
| 641   for (size_t i = 0; i < parsed_log_.GetNumberOfEvents(); i++) { | 590   for (size_t i = 0; i < parsed_log_.GetNumberOfEvents(); i++) { | 
| 642     ParsedRtcEventLog::EventType event_type = parsed_log_.GetEventType(i); | 591     ParsedRtcEventLog::EventType event_type = parsed_log_.GetEventType(i); | 
| 643     if (event_type == ParsedRtcEventLog::RTP_EVENT) { | 592     if (event_type == ParsedRtcEventLog::RTP_EVENT) { | 
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 701   plot->yaxis_label = "Bitrate (kbps)"; | 650   plot->yaxis_label = "Bitrate (kbps)"; | 
| 702   if (desired_direction == webrtc::PacketDirection::kIncomingPacket) { | 651   if (desired_direction == webrtc::PacketDirection::kIncomingPacket) { | 
| 703     plot->title = "Incoming bitrate per stream"; | 652     plot->title = "Incoming bitrate per stream"; | 
| 704   } else if (desired_direction == webrtc::PacketDirection::kOutgoingPacket) { | 653   } else if (desired_direction == webrtc::PacketDirection::kOutgoingPacket) { | 
| 705     plot->title = "Outgoing bitrate per stream"; | 654     plot->title = "Outgoing bitrate per stream"; | 
| 706   } | 655   } | 
| 707 } | 656 } | 
| 708 | 657 | 
| 709 }  // namespace plotting | 658 }  // namespace plotting | 
| 710 }  // namespace webrtc | 659 }  // namespace webrtc | 
| OLD | NEW | 
|---|