Fixing bug in SimulatedNetwork where packets stop.

Bug: webrtc:9952
Change-Id: I68491f1d18fee317165999453776a35cea41e71f
Reviewed-on: https://webrtc-review.googlesource.com/c/109009
Commit-Queue: Sebastian Jansson <srte@webrtc.org>
Reviewed-by: Christoffer Rodbro <crodbro@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#25531}
diff --git a/call/BUILD.gn b/call/BUILD.gn
index 0b65c3c..db82884 100644
--- a/call/BUILD.gn
+++ b/call/BUILD.gn
@@ -260,6 +260,9 @@
   ]
   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 ee58dce..77be148 100644
--- a/call/simulated_network.cc
+++ b/call/simulated_network.cc
@@ -13,6 +13,7 @@
 #include <algorithm>
 #include <cmath>
 #include <utility>
+#include "api/units/data_rate.h"
 
 namespace webrtc {
 
@@ -26,6 +27,9 @@
 
 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 @@
     // 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<int64_t>(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<int64_t> 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 7593464..e978027 100644
--- a/call/simulated_network.h
+++ b/call/simulated_network.h
@@ -49,6 +49,7 @@
     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 @@
   std::queue<PacketInfo> capacity_link_ RTC_GUARDED_BY(process_lock_);
   Random random_;
 
-  std::deque<PacketInfo> delay_link_;
+  std::deque<PacketInfo> delay_link_ RTC_GUARDED_BY(process_lock_);
 
   // Link configuration.
   Config config_ RTC_GUARDED_BY(config_lock_);