Add outgoing TWCC loss and missing packet feedback plots to event log analyzer.
Bug: webrtc:12707 Change-Id: I737177e6b6737c8c2e7d8803a68e29e9998ba9f8 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/321140 Reviewed-by: Björn Terelius <terelius@webrtc.org> Commit-Queue: Diep Bui <diepbp@webrtc.org> Cr-Commit-Position: refs/heads/main@{#40925}
This commit is contained in:
parent
ec48886da9
commit
636c3f24b8
@ -12,6 +12,7 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <deque>
|
||||
#include <limits>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
@ -406,6 +407,12 @@ RtpPacketReceived RtpPacketForBWEFromHeader(const RTPHeader& header) {
|
||||
return rtp_packet;
|
||||
}
|
||||
|
||||
struct PacketLossSummary {
|
||||
size_t num_packets = 0;
|
||||
size_t num_lost_packets = 0;
|
||||
Timestamp base_time = Timestamp::MinusInfinity();
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
EventLogAnalyzer::EventLogAnalyzer(const ParsedRtcEventLog& log,
|
||||
@ -1298,6 +1305,100 @@ void EventLogAnalyzer::CreateGoogCcSimulationGraph(Plot* plot) {
|
||||
plot->SetTitle("Simulated BWE behavior");
|
||||
}
|
||||
|
||||
void EventLogAnalyzer::CreateOutgoingTWCCLossRateGraph(Plot* plot) {
|
||||
TimeSeries loss_rate_series("Loss rate (from packet feedback)",
|
||||
LineStyle::kLine, PointStyle::kHighlight);
|
||||
TimeSeries average_loss_rate_series("Average loss rate last 5s",
|
||||
LineStyle::kLine, PointStyle::kHighlight);
|
||||
TimeSeries missing_feedback_series("Missing feedback", LineStyle::kNone,
|
||||
PointStyle::kHighlight);
|
||||
PacketLossSummary window_summary;
|
||||
Timestamp last_observation_receive_time = Timestamp::Zero();
|
||||
|
||||
// Use loss based bwe 2 observation duration and observation window size.
|
||||
constexpr TimeDelta kObservationDuration = TimeDelta::Millis(250);
|
||||
constexpr uint32_t kObservationWindowSize = 20;
|
||||
std::deque<PacketLossSummary> observations;
|
||||
SeqNumUnwrapper<uint16_t> unwrapper;
|
||||
int64_t last_acked = 1;
|
||||
if (!parsed_log_.transport_feedbacks(kIncomingPacket).empty()) {
|
||||
last_acked =
|
||||
unwrapper.Unwrap(parsed_log_.transport_feedbacks(kIncomingPacket)[0]
|
||||
.transport_feedback.GetBaseSequence());
|
||||
}
|
||||
for (auto& feedback : parsed_log_.transport_feedbacks(kIncomingPacket)) {
|
||||
const rtcp::TransportFeedback& transport_feedback =
|
||||
feedback.transport_feedback;
|
||||
size_t base_seq_num =
|
||||
unwrapper.Unwrap(transport_feedback.GetBaseSequence());
|
||||
// Collect packets that do not have feedback, which are from the last acked
|
||||
// packet, to the current base packet.
|
||||
for (size_t seq_num = last_acked; seq_num < base_seq_num; ++seq_num) {
|
||||
missing_feedback_series.points.emplace_back(
|
||||
config_.GetCallTimeSec(feedback.timestamp),
|
||||
100 + seq_num - last_acked);
|
||||
}
|
||||
last_acked = base_seq_num + transport_feedback.GetPacketStatusCount();
|
||||
|
||||
// Compute loss rate from the transport feedback.
|
||||
auto loss_rate =
|
||||
static_cast<float>((transport_feedback.GetPacketStatusCount() -
|
||||
transport_feedback.GetReceivedPackets().size()) *
|
||||
100.0 / transport_feedback.GetPacketStatusCount());
|
||||
loss_rate_series.points.emplace_back(
|
||||
config_.GetCallTimeSec(feedback.timestamp), loss_rate);
|
||||
|
||||
// Compute loss rate in a window of kObservationWindowSize.
|
||||
if (window_summary.num_packets == 0) {
|
||||
window_summary.base_time = feedback.log_time();
|
||||
}
|
||||
window_summary.num_packets += transport_feedback.GetPacketStatusCount();
|
||||
window_summary.num_lost_packets +=
|
||||
transport_feedback.GetPacketStatusCount() -
|
||||
transport_feedback.GetReceivedPackets().size();
|
||||
|
||||
const Timestamp last_received_time = feedback.log_time();
|
||||
const TimeDelta observation_duration =
|
||||
window_summary.base_time == Timestamp::Zero()
|
||||
? TimeDelta::Zero()
|
||||
: last_received_time - window_summary.base_time;
|
||||
if (observation_duration > kObservationDuration) {
|
||||
last_observation_receive_time = last_received_time;
|
||||
observations.push_back(window_summary);
|
||||
if (observations.size() > kObservationWindowSize) {
|
||||
observations.pop_front();
|
||||
}
|
||||
|
||||
// Compute average loss rate in a number of windows.
|
||||
int total_packets = 0;
|
||||
int total_loss = 0;
|
||||
for (const auto& observation : observations) {
|
||||
total_loss += observation.num_lost_packets;
|
||||
total_packets += observation.num_packets;
|
||||
}
|
||||
if (total_packets > 0) {
|
||||
float average_loss_rate = total_loss * 100.0 / total_packets;
|
||||
average_loss_rate_series.points.emplace_back(
|
||||
config_.GetCallTimeSec(feedback.timestamp), average_loss_rate);
|
||||
} else {
|
||||
average_loss_rate_series.points.emplace_back(
|
||||
config_.GetCallTimeSec(feedback.timestamp), 0);
|
||||
}
|
||||
window_summary = PacketLossSummary();
|
||||
}
|
||||
}
|
||||
// Add the data set to the plot.
|
||||
plot->AppendTimeSeriesIfNotEmpty(std::move(loss_rate_series));
|
||||
plot->AppendTimeSeriesIfNotEmpty(std::move(average_loss_rate_series));
|
||||
plot->AppendTimeSeriesIfNotEmpty(std::move(missing_feedback_series));
|
||||
|
||||
plot->SetXAxis(config_.CallBeginTimeSec(), config_.CallEndTimeSec(),
|
||||
"Time (s)", kLeftMargin, kRightMargin);
|
||||
plot->SetSuggestedYAxis(0, 100, "Loss rate (percent)", kBottomMargin,
|
||||
kTopMargin);
|
||||
plot->SetTitle("Outgoing loss rate (from TWCC feedback)");
|
||||
}
|
||||
|
||||
void EventLogAnalyzer::CreateSendSideBweSimulationGraph(Plot* plot) {
|
||||
using RtpPacketType = LoggedRtpPacketOutgoing;
|
||||
using TransportFeedbackType = LoggedRtcpPacketTransportFeedback;
|
||||
|
||||
@ -67,6 +67,7 @@ class EventLogAnalyzer {
|
||||
void CreateStreamBitrateGraph(PacketDirection direction, Plot* plot);
|
||||
void CreateBitrateAllocationGraph(PacketDirection direction, Plot* plot);
|
||||
|
||||
void CreateOutgoingTWCCLossRateGraph(Plot* plot);
|
||||
void CreateGoogCcSimulationGraph(Plot* plot);
|
||||
void CreateSendSideBweSimulationGraph(Plot* plot);
|
||||
void CreateReceiveSideBweSimulationGraph(Plot* plot);
|
||||
|
||||
@ -227,7 +227,7 @@ int main(int argc, char* argv[]) {
|
||||
{"sendside_bwe",
|
||||
{"outgoing_packet_sizes", "outgoing_bitrate", "outgoing_stream_bitrate",
|
||||
"simulated_sendside_bwe", "network_delay_feedback",
|
||||
"fraction_loss_feedback"}},
|
||||
"fraction_loss_feedback", "outgoing_twcc_loss"}},
|
||||
{"receiveside_bwe",
|
||||
{"incoming_packet_sizes", "incoming_delay", "incoming_loss_rate",
|
||||
"incoming_bitrate", "incoming_stream_bitrate",
|
||||
@ -377,6 +377,9 @@ int main(int argc, char* argv[]) {
|
||||
plots.RegisterPlot("simulated_goog_cc", [&](Plot* plot) {
|
||||
analyzer.CreateGoogCcSimulationGraph(plot);
|
||||
});
|
||||
plots.RegisterPlot("outgoing_twcc_loss", [&](Plot* plot) {
|
||||
analyzer.CreateOutgoingTWCCLossRateGraph(plot);
|
||||
});
|
||||
plots.RegisterPlot("network_delay_feedback", [&](Plot* plot) {
|
||||
analyzer.CreateNetworkDelayFeedbackGraph(plot);
|
||||
});
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user