webrtc/rtc_tools/rtc_event_log_visualizer/log_simulation.cc
Danil Chapovalov f20ed3e8ad Add option to provide Environment for CongestionConroller construction
This would allow network controllers, GoogCcNetworkController in particular to have access to Environment at construction and thus it can rely on propagated field trials and won't need to fallback to the global field trial string

Bug: webrtc:42220378
Change-Id: I36099522e3866a89a8c8d6303da03f7d5b1cad8e
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/350201
Reviewed-by: Björn Terelius <terelius@webrtc.org>
Commit-Queue: Danil Chapovalov <danilchap@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#42260}
2024-05-08 12:46:23 +00:00

226 lines
8.7 KiB
C++

/*
* Copyright 2019 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "rtc_tools/rtc_event_log_visualizer/log_simulation.h"
#include <algorithm>
#include <cstdint>
#include <functional>
#include <memory>
#include <utility>
#include "api/environment/environment_factory.h"
#include "api/transport/network_control.h"
#include "api/transport/network_types.h"
#include "api/units/data_rate.h"
#include "api/units/time_delta.h"
#include "api/units/timestamp.h"
#include "logging/rtc_event_log/events/logged_rtp_rtcp.h"
#include "logging/rtc_event_log/events/rtc_event_ice_candidate_pair_config.h"
#include "logging/rtc_event_log/events/rtc_event_probe_cluster_created.h"
#include "logging/rtc_event_log/rtc_event_log_parser.h"
#include "logging/rtc_event_log/rtc_event_processor.h"
#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
#include "modules/rtp_rtcp/source/time_util.h"
#include "rtc_base/network/sent_packet.h"
#include "system_wrappers/include/clock.h"
namespace webrtc {
LogBasedNetworkControllerSimulation::LogBasedNetworkControllerSimulation(
std::unique_ptr<NetworkControllerFactoryInterface> factory,
std::function<void(const NetworkControlUpdate&, Timestamp)> update_handler)
: update_handler_(update_handler), factory_(std::move(factory)) {}
LogBasedNetworkControllerSimulation::~LogBasedNetworkControllerSimulation() {}
void LogBasedNetworkControllerSimulation::HandleStateUpdate(
const NetworkControlUpdate& update) {
update_handler_(update, current_time_);
}
void LogBasedNetworkControllerSimulation::ProcessUntil(Timestamp to_time) {
if (last_process_.IsInfinite()) {
NetworkControllerConfig config(CreateEnvironment(&null_event_log_));
config.constraints.at_time = to_time;
config.constraints.min_data_rate = DataRate::KilobitsPerSec(30);
config.constraints.starting_rate = DataRate::KilobitsPerSec(300);
controller_ = factory_->Create(config);
}
if (last_process_.IsInfinite() ||
to_time - last_process_ > TimeDelta::Seconds(1)) {
last_process_ = to_time;
current_time_ = to_time;
ProcessInterval msg;
msg.at_time = to_time;
HandleStateUpdate(controller_->OnProcessInterval(msg));
} else {
while (last_process_ + factory_->GetProcessInterval() <= to_time) {
last_process_ += factory_->GetProcessInterval();
current_time_ = last_process_;
ProcessInterval msg;
msg.at_time = current_time_;
HandleStateUpdate(controller_->OnProcessInterval(msg));
}
current_time_ = to_time;
}
}
void LogBasedNetworkControllerSimulation::OnProbeCreated(
const LoggedBweProbeClusterCreatedEvent& probe_cluster) {
pending_probes_.push_back({probe_cluster, 0, 0});
}
void LogBasedNetworkControllerSimulation::OnPacketSent(
const LoggedPacketInfo& packet) {
ProcessUntil(packet.log_packet_time);
if (packet.has_transport_seq_no) {
PacedPacketInfo probe_info;
if (!pending_probes_.empty() &&
packet.media_type == LoggedMediaType::kVideo) {
auto& probe = pending_probes_.front();
probe_info.probe_cluster_id = probe.event.id;
probe_info.send_bitrate = DataRate::BitsPerSec(probe.event.bitrate_bps);
probe_info.probe_cluster_min_bytes = probe.event.min_bytes;
probe_info.probe_cluster_min_probes = probe.event.min_packets;
probe.packets_sent++;
probe.bytes_sent += packet.size + packet.overhead;
if (probe.bytes_sent >= probe.event.min_bytes &&
probe.packets_sent >= probe.event.min_packets) {
pending_probes_.pop_front();
}
}
RtpPacketSendInfo packet_info;
packet_info.media_ssrc = packet.ssrc;
packet_info.transport_sequence_number = packet.transport_seq_no;
packet_info.rtp_sequence_number = packet.stream_seq_no;
packet_info.length = packet.size;
packet_info.pacing_info = probe_info;
transport_feedback_.AddPacket(packet_info, packet.overhead,
packet.log_packet_time);
}
rtc::SentPacket sent_packet;
sent_packet.send_time_ms = packet.log_packet_time.ms();
sent_packet.info.included_in_allocation = true;
sent_packet.info.packet_size_bytes = packet.size + packet.overhead;
if (packet.has_transport_seq_no) {
sent_packet.packet_id = packet.transport_seq_no;
sent_packet.info.included_in_feedback = true;
}
auto msg = transport_feedback_.ProcessSentPacket(sent_packet);
if (msg)
HandleStateUpdate(controller_->OnSentPacket(*msg));
}
void LogBasedNetworkControllerSimulation::OnFeedback(
const LoggedRtcpPacketTransportFeedback& feedback) {
auto feedback_time = Timestamp::Millis(feedback.log_time_ms());
ProcessUntil(feedback_time);
auto msg = transport_feedback_.ProcessTransportFeedback(
feedback.transport_feedback, feedback_time);
if (msg)
HandleStateUpdate(controller_->OnTransportPacketsFeedback(*msg));
}
void LogBasedNetworkControllerSimulation::OnReceiverReport(
const LoggedRtcpPacketReceiverReport& report) {
if (report.rr.report_blocks().empty())
return;
auto report_time = Timestamp::Millis(report.log_time_ms());
ProcessUntil(report_time);
int packets_delta = 0;
int lost_delta = 0;
for (auto& block : report.rr.report_blocks()) {
auto it = last_report_blocks_.find(block.source_ssrc());
if (it != last_report_blocks_.end()) {
packets_delta +=
block.extended_high_seq_num() - it->second.extended_high_seq_num();
lost_delta += block.cumulative_lost() - it->second.cumulative_lost();
}
last_report_blocks_[block.source_ssrc()] = block;
}
if (packets_delta > lost_delta) {
TransportLossReport msg;
msg.packets_lost_delta = lost_delta;
msg.packets_received_delta = packets_delta - lost_delta;
msg.receive_time = report_time;
msg.start_time = last_report_block_time_;
msg.end_time = report_time;
last_report_block_time_ = report_time;
HandleStateUpdate(controller_->OnTransportLossReport(msg));
}
Clock* clock = Clock::GetRealTimeClock();
TimeDelta rtt = TimeDelta::PlusInfinity();
for (auto& rb : report.rr.report_blocks()) {
if (rb.last_sr()) {
Timestamp report_log_time = Timestamp::Micros(report.log_time_us());
uint32_t receive_time_ntp =
CompactNtp(clock->ConvertTimestampToNtpTime(report_log_time));
uint32_t rtt_ntp =
receive_time_ntp - rb.delay_since_last_sr() - rb.last_sr();
rtt = std::min(rtt, CompactNtpRttToTimeDelta(rtt_ntp));
}
}
if (rtt.IsFinite()) {
RoundTripTimeUpdate msg;
msg.receive_time = report_time;
msg.round_trip_time = rtt;
HandleStateUpdate(controller_->OnRoundTripTimeUpdate(msg));
}
}
void LogBasedNetworkControllerSimulation::OnIceConfig(
const LoggedIceCandidatePairConfig& candidate) {
if (candidate.type == IceCandidatePairConfigType::kSelected) {
auto log_time = Timestamp::Micros(candidate.log_time_us());
ProcessUntil(log_time);
NetworkRouteChange msg;
msg.at_time = log_time;
msg.constraints.min_data_rate = DataRate::KilobitsPerSec(30);
msg.constraints.starting_rate = DataRate::KilobitsPerSec(300);
msg.constraints.at_time = log_time;
HandleStateUpdate(controller_->OnNetworkRouteChange(msg));
}
}
void LogBasedNetworkControllerSimulation::ProcessEventsInLog(
const ParsedRtcEventLog& parsed_log_) {
auto packet_infos = parsed_log_.GetOutgoingPacketInfos();
RtcEventProcessor processor;
processor.AddEvents(
parsed_log_.bwe_probe_cluster_created_events(),
[this](const LoggedBweProbeClusterCreatedEvent& probe_cluster) {
OnProbeCreated(probe_cluster);
});
processor.AddEvents(
packet_infos,
[this](const LoggedPacketInfo& packet) { OnPacketSent(packet); },
PacketDirection::kOutgoingPacket);
processor.AddEvents(
parsed_log_.transport_feedbacks(PacketDirection::kIncomingPacket),
[this](const LoggedRtcpPacketTransportFeedback& feedback) {
OnFeedback(feedback);
},
PacketDirection::kIncomingPacket);
processor.AddEvents(
parsed_log_.receiver_reports(PacketDirection::kIncomingPacket),
[this](const LoggedRtcpPacketReceiverReport& report) {
OnReceiverReport(report);
},
PacketDirection::kIncomingPacket);
processor.AddEvents(parsed_log_.ice_candidate_pair_configs(),
[this](const LoggedIceCandidatePairConfig& candidate) {
OnIceConfig(candidate);
});
processor.ProcessEventsInOrder();
}
} // namespace webrtc