diff --git a/call/BUILD.gn b/call/BUILD.gn index 0b65c3c60a..db82884cfd 100644 --- a/call/BUILD.gn +++ b/call/BUILD.gn @@ -260,6 +260,9 @@ rtc_source_set("simulated_network") { ] deps = [ "../api:simulated_network_api", + "../api/units:data_rate", + "../api/units:data_size", + "../api/units:time_delta", "../rtc_base:rtc_base_approved", "//third_party/abseil-cpp/absl/memory", "//third_party/abseil-cpp/absl/types:optional", diff --git a/call/simulated_network.cc b/call/simulated_network.cc index ee58dce718..77be14821c 100644 --- a/call/simulated_network.cc +++ b/call/simulated_network.cc @@ -13,6 +13,7 @@ #include #include #include +#include "api/units/data_rate.h" namespace webrtc { @@ -26,6 +27,9 @@ SimulatedNetwork::~SimulatedNetwork() = default; void SimulatedNetwork::SetConfig(const SimulatedNetwork::Config& config) { rtc::CritScope crit(&config_lock_); + if (config_.link_capacity_kbps != config.link_capacity_kbps) { + reset_capacity_delay_error_ = true; + } config_ = config; // Shallow copy of the struct. double prob_loss = config.loss_percent / 100.0; if (config_.avg_burst_loss_length == -1) { @@ -64,42 +68,45 @@ bool SimulatedNetwork::EnqueuePacket(PacketInFlightInfo packet) { // Too many packet on the link, drop this one. return false; } - - // Delay introduced by the link capacity. - int64_t capacity_delay_ms = 0; - if (config.link_capacity_kbps > 0) { - // Using bytes per millisecond to avoid losing precision. - const int64_t bytes_per_millisecond = config.link_capacity_kbps / 8; - // To round to the closest millisecond we add half a milliseconds worth of - // bytes to the delay calculation. - capacity_delay_ms = (packet.size + capacity_delay_error_bytes_ + - bytes_per_millisecond / 2) / - bytes_per_millisecond; - capacity_delay_error_bytes_ += - packet.size - capacity_delay_ms * bytes_per_millisecond; - } int64_t network_start_time_us = packet.send_time_us; - { rtc::CritScope crit(&config_lock_); + if (reset_capacity_delay_error_) { + capacity_delay_error_bytes_ = 0; + reset_capacity_delay_error_ = false; + } if (pause_transmission_until_us_) { network_start_time_us = std::max(network_start_time_us, *pause_transmission_until_us_); pause_transmission_until_us_.reset(); } } + + // Delay introduced by the link capacity. + TimeDelta capacity_delay = TimeDelta::Zero(); + if (config.link_capacity_kbps > 0) { + const DataRate link_capacity = DataRate::kbps(config.link_capacity_kbps); + int64_t compensated_size = + static_cast(packet.size) + capacity_delay_error_bytes_; + capacity_delay = DataSize::bytes(compensated_size) / link_capacity; + + capacity_delay_error_bytes_ += + packet.size - (capacity_delay * link_capacity).bytes(); + } + // Check if there already are packets on the link and change network start // time forward if there is. if (!capacity_link_.empty() && network_start_time_us < capacity_link_.back().arrival_time_us) network_start_time_us = capacity_link_.back().arrival_time_us; - int64_t arrival_time_us = network_start_time_us + capacity_delay_ms * 1000; + int64_t arrival_time_us = network_start_time_us + capacity_delay.us(); capacity_link_.push({packet, arrival_time_us}); return true; } absl::optional SimulatedNetwork::NextDeliveryTimeUs() const { + rtc::CritScope crit(&process_lock_); if (!delay_link_.empty()) return delay_link_.begin()->arrival_time_us; return absl::nullopt; diff --git a/call/simulated_network.h b/call/simulated_network.h index 75934645e5..e978027092 100644 --- a/call/simulated_network.h +++ b/call/simulated_network.h @@ -49,6 +49,7 @@ class SimulatedNetwork : public NetworkBehaviorInterface { int64_t arrival_time_us; }; rtc::CriticalSection config_lock_; + bool reset_capacity_delay_error_ RTC_GUARDED_BY(config_lock_) = false; // |process_lock| guards the data structures involved in delay and loss // processes, such as the packet queues. @@ -56,7 +57,7 @@ class SimulatedNetwork : public NetworkBehaviorInterface { std::queue capacity_link_ RTC_GUARDED_BY(process_lock_); Random random_; - std::deque delay_link_; + std::deque delay_link_ RTC_GUARDED_BY(process_lock_); // Link configuration. Config config_ RTC_GUARDED_BY(config_lock_);