diff --git a/rtc_tools/event_log_visualizer/analyzer.cc b/rtc_tools/event_log_visualizer/analyzer.cc index 75558450ae..4ddd68c9e4 100644 --- a/rtc_tools/event_log_visualizer/analyzer.cc +++ b/rtc_tools/event_log_visualizer/analyzer.cc @@ -1458,6 +1458,61 @@ void EventLogAnalyzer::CreateTimestampGraph(PacketDirection direction, plot->SetTitle(GetDirectionAsString(direction) + " timestamps"); } +void EventLogAnalyzer::CreateSenderAndReceiverReportPlot( + PacketDirection direction, + rtc::FunctionView fy, + std::string title, + std::string yaxis_label, + Plot* plot) { + std::map sr_reports_by_ssrc; + const auto& sender_reports = parsed_log_.sender_reports(direction); + for (const auto& rtcp : sender_reports) { + float x = ToCallTimeSec(rtcp.log_time_us()); + uint32_t ssrc = rtcp.sr.sender_ssrc(); + for (const auto& block : rtcp.sr.report_blocks()) { + float y = fy(block); + auto sr_report_it = sr_reports_by_ssrc.find(ssrc); + bool inserted; + if (sr_report_it == sr_reports_by_ssrc.end()) { + std::tie(sr_report_it, inserted) = sr_reports_by_ssrc.emplace( + ssrc, TimeSeries(GetStreamName(direction, ssrc) + " Sender Reports", + LineStyle::kLine, PointStyle::kHighlight)); + } + sr_report_it->second.points.emplace_back(x, y); + } + } + for (auto& kv : sr_reports_by_ssrc) { + plot->AppendTimeSeries(std::move(kv.second)); + } + + std::map rr_reports_by_ssrc; + const auto& receiver_reports = parsed_log_.receiver_reports(direction); + for (const auto& rtcp : receiver_reports) { + float x = ToCallTimeSec(rtcp.log_time_us()); + uint32_t ssrc = rtcp.rr.sender_ssrc(); + for (const auto& block : rtcp.rr.report_blocks()) { + float y = fy(block); + auto rr_report_it = rr_reports_by_ssrc.find(ssrc); + bool inserted; + if (rr_report_it == rr_reports_by_ssrc.end()) { + std::tie(rr_report_it, inserted) = rr_reports_by_ssrc.emplace( + ssrc, + TimeSeries(GetStreamName(direction, ssrc) + " Receiver Reports", + LineStyle::kLine, PointStyle::kHighlight)); + } + rr_report_it->second.points.emplace_back(x, y); + } + } + for (auto& kv : rr_reports_by_ssrc) { + plot->AppendTimeSeries(std::move(kv.second)); + } + + plot->SetXAxis(ToCallTimeSec(begin_time_), call_duration_s_, "Time (s)", + kLeftMargin, kRightMargin); + plot->SetSuggestedYAxis(0, 1, yaxis_label, kBottomMargin, kTopMargin); + plot->SetTitle(title); +} + void EventLogAnalyzer::CreateAudioEncoderTargetBitrateGraph(Plot* plot) { TimeSeries time_series("Audio encoder target bitrate", LineStyle::kLine, PointStyle::kHighlight); diff --git a/rtc_tools/event_log_visualizer/analyzer.h b/rtc_tools/event_log_visualizer/analyzer.h index 22101b6585..4b8c27c951 100644 --- a/rtc_tools/event_log_visualizer/analyzer.h +++ b/rtc_tools/event_log_visualizer/analyzer.h @@ -64,6 +64,12 @@ class EventLogAnalyzer { void CreatePacerDelayGraph(Plot* plot); void CreateTimestampGraph(PacketDirection direction, Plot* plot); + void CreateSenderAndReceiverReportPlot( + PacketDirection direction, + rtc::FunctionView fy, + std::string title, + std::string yaxis_label, + Plot* plot); void CreateAudioEncoderTargetBitrateGraph(Plot* plot); void CreateAudioEncoderFrameLengthGraph(Plot* plot); diff --git a/rtc_tools/event_log_visualizer/main.cc b/rtc_tools/event_log_visualizer/main.cc index b1fc0d2847..fb497db577 100644 --- a/rtc_tools/event_log_visualizer/main.cc +++ b/rtc_tools/event_log_visualizer/main.cc @@ -97,6 +97,12 @@ DEFINE_bool(plot_pacer_delay, DEFINE_bool(plot_timestamps, false, "Plot the rtp timestamps of all rtp and rtcp packets over time."); +DEFINE_bool(plot_rtcp_details, + false, + "Plot the contents of all report blocks in all sender and receiver " + "reports. This includes fraction lost, cumulative number of lost " + "packets, extended highest sequence number and time since last " + "received SR."); DEFINE_bool(plot_audio_encoder_bitrate_bps, false, "Plot the audio encoder target bitrate."); @@ -305,6 +311,59 @@ int main(int argc, char* argv[]) { analyzer.CreateTimestampGraph(webrtc::kOutgoingPacket, collection->AppendNewPlot()); } + if (FLAG_plot_rtcp_details) { + auto GetFractionLost = [](const webrtc::rtcp::ReportBlock& block) -> float { + return static_cast(block.fraction_lost()) / 256 * 100; + }; + analyzer.CreateSenderAndReceiverReportPlot( + webrtc::kIncomingPacket, GetFractionLost, + "Fraction lost (incoming RTCP)", "Loss rate (percent)", + collection->AppendNewPlot()); + analyzer.CreateSenderAndReceiverReportPlot( + webrtc::kOutgoingPacket, GetFractionLost, + "Fraction lost (outgoing RTCP)", "Loss rate (percent)", + collection->AppendNewPlot()); + + auto GetCumulativeLost = + [](const webrtc::rtcp::ReportBlock& block) -> float { + return block.cumulative_lost_signed(); + }; + analyzer.CreateSenderAndReceiverReportPlot( + webrtc::kIncomingPacket, GetCumulativeLost, + "Cumulative lost packets (incoming RTCP)", "Packets", + collection->AppendNewPlot()); + analyzer.CreateSenderAndReceiverReportPlot( + webrtc::kOutgoingPacket, GetCumulativeLost, + "Cumulative lost packets (outgoing RTCP)", "Packets", + collection->AppendNewPlot()); + + auto GetHighestSeqNumber = + [](const webrtc::rtcp::ReportBlock& block) -> float { + return block.extended_high_seq_num(); + }; + analyzer.CreateSenderAndReceiverReportPlot( + webrtc::kIncomingPacket, GetHighestSeqNumber, + "Highest sequence number (incoming RTCP)", "Seqence number", + collection->AppendNewPlot()); + analyzer.CreateSenderAndReceiverReportPlot( + webrtc::kOutgoingPacket, GetHighestSeqNumber, + "Highest sequence number (outgoing RTCP)", "Seqence number", + collection->AppendNewPlot()); + + auto DelaySinceLastSr = + [](const webrtc::rtcp::ReportBlock& block) -> float { + return static_cast(block.delay_since_last_sr()) / 65536; + }; + analyzer.CreateSenderAndReceiverReportPlot( + webrtc::kIncomingPacket, DelaySinceLastSr, + "Delay since last received sender report (incoming RTCP)", "Time (s)", + collection->AppendNewPlot()); + analyzer.CreateSenderAndReceiverReportPlot( + webrtc::kOutgoingPacket, DelaySinceLastSr, + "Delay since last received sender report (outgoing RTCP)", "Time (s)", + collection->AppendNewPlot()); + } + if (FLAG_plot_pacer_delay) { analyzer.CreatePacerDelayGraph(collection->AppendNewPlot()); } @@ -410,6 +469,7 @@ void SetAllPlotFlags(bool setting) { FLAG_plot_network_delay_feedback = setting; FLAG_plot_fraction_loss_feedback = setting; FLAG_plot_timestamps = setting; + FLAG_plot_rtcp_details = setting; FLAG_plot_audio_encoder_bitrate_bps = setting; FLAG_plot_audio_encoder_frame_length_ms = setting; FLAG_plot_audio_encoder_packet_loss = setting;