Modernize style in RemoteBitrateEstimatorAbsSendTime implementation

Use dedicated DataSize/DataRate/Time classes instead plain integers
this avoid subtle overflows and makes code easier to follow.

Hide helper structs Probe and Cluster as private structs.
User foreach loops where possible.
Make private constants constexpr instead of using enum hack

Bug: None
Change-Id: I3e71dc1254d7ff8ce71e051de53f0459bfa5264d
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/219795
Commit-Queue: Danil Chapovalov <danilchap@webrtc.org>
Reviewed-by: Björn Terelius <terelius@webrtc.org>
Reviewed-by: Christoffer Rodbro <crodbro@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#34222}
diff --git a/modules/remote_bitrate_estimator/BUILD.gn b/modules/remote_bitrate_estimator/BUILD.gn
index 8507703..a7f1d59 100644
--- a/modules/remote_bitrate_estimator/BUILD.gn
+++ b/modules/remote_bitrate_estimator/BUILD.gn
@@ -47,6 +47,8 @@
     "../../api/transport:network_control",
     "../../api/transport:webrtc_key_value_config",
     "../../api/units:data_rate",
+    "../../api/units:data_size",
+    "../../api/units:time_delta",
     "../../api/units:timestamp",
     "../../modules:module_api",
     "../../modules:module_api_public",
diff --git a/modules/remote_bitrate_estimator/remote_bitrate_estimator_abs_send_time.cc b/modules/remote_bitrate_estimator/remote_bitrate_estimator_abs_send_time.cc
index 4196f6d..ae960ab 100644
--- a/modules/remote_bitrate_estimator/remote_bitrate_estimator_abs_send_time.cc
+++ b/modules/remote_bitrate_estimator/remote_bitrate_estimator_abs_send_time.cc
@@ -13,18 +13,36 @@
 #include <math.h>
 
 #include <algorithm>
+#include <memory>
+#include <utility>
 
 #include "api/transport/field_trial_based_config.h"
+#include "api/units/data_rate.h"
+#include "api/units/data_size.h"
+#include "api/units/time_delta.h"
+#include "api/units/timestamp.h"
 #include "modules/remote_bitrate_estimator/include/bwe_defines.h"
 #include "modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h"
 #include "rtc_base/checks.h"
-#include "rtc_base/constructor_magic.h"
 #include "rtc_base/logging.h"
 #include "rtc_base/thread_annotations.h"
 #include "system_wrappers/include/metrics.h"
 
 namespace webrtc {
 namespace {
+
+constexpr TimeDelta kMinClusterDelta = TimeDelta::Millis(1);
+constexpr TimeDelta kInitialProbingInterval = TimeDelta::Seconds(2);
+constexpr int kTimestampGroupLengthMs = 5;
+constexpr int kAbsSendTimeInterArrivalUpshift = 8;
+constexpr int kInterArrivalShift =
+    RTPHeaderExtension::kAbsSendTimeFraction + kAbsSendTimeInterArrivalUpshift;
+constexpr int kMinClusterSize = 4;
+constexpr int kMaxProbePackets = 15;
+constexpr int kExpectedNumberOfProbes = 3;
+constexpr double kTimestampToMs =
+    1000.0 / static_cast<double>(1 << kInterArrivalShift);
+
 absl::optional<DataRate> OptionalRateFromOptionalBps(
     absl::optional<int> bitrate_bps) {
   if (bitrate_bps) {
@@ -33,62 +51,48 @@
     return absl::nullopt;
   }
 }
-}  // namespace
-
-enum {
-  kTimestampGroupLengthMs = 5,
-  kAbsSendTimeInterArrivalUpshift = 8,
-  kInterArrivalShift = RTPHeaderExtension::kAbsSendTimeFraction +
-                       kAbsSendTimeInterArrivalUpshift,
-  kInitialProbingIntervalMs = 2000,
-  kMinClusterSize = 4,
-  kMaxProbePackets = 15,
-  kExpectedNumberOfProbes = 3
-};
-
-static const double kTimestampToMs =
-    1000.0 / static_cast<double>(1 << kInterArrivalShift);
 
 template <typename K, typename V>
 std::vector<K> Keys(const std::map<K, V>& map) {
   std::vector<K> keys;
   keys.reserve(map.size());
-  for (typename std::map<K, V>::const_iterator it = map.begin();
-       it != map.end(); ++it) {
-    keys.push_back(it->first);
+  for (const auto& kv_pair : map) {
+    keys.push_back(kv_pair.first);
   }
   return keys;
 }
 
-uint32_t ConvertMsTo24Bits(int64_t time_ms) {
-  uint32_t time_24_bits =
-      static_cast<uint32_t>(((static_cast<uint64_t>(time_ms)
-                              << RTPHeaderExtension::kAbsSendTimeFraction) +
-                             500) /
-                            1000) &
-      0x00FFFFFF;
-  return time_24_bits;
-}
+}  // namespace
 
 RemoteBitrateEstimatorAbsSendTime::~RemoteBitrateEstimatorAbsSendTime() =
     default;
 
 bool RemoteBitrateEstimatorAbsSendTime::IsWithinClusterBounds(
-    int send_delta_ms,
+    TimeDelta send_delta,
     const Cluster& cluster_aggregate) {
   if (cluster_aggregate.count == 0)
     return true;
-  float cluster_mean = cluster_aggregate.send_mean_ms /
-                       static_cast<float>(cluster_aggregate.count);
-  return fabs(static_cast<float>(send_delta_ms) - cluster_mean) < 2.5f;
+  TimeDelta cluster_mean =
+      cluster_aggregate.send_mean / cluster_aggregate.count;
+  return (send_delta - cluster_mean).Abs() < TimeDelta::Micros(2'500);
 }
 
-void RemoteBitrateEstimatorAbsSendTime::AddCluster(std::list<Cluster>* clusters,
-                                                   Cluster* cluster) {
-  cluster->send_mean_ms /= static_cast<float>(cluster->count);
-  cluster->recv_mean_ms /= static_cast<float>(cluster->count);
-  cluster->mean_size /= cluster->count;
-  clusters->push_back(*cluster);
+void RemoteBitrateEstimatorAbsSendTime::MaybeAddCluster(
+    const Cluster& cluster_aggregate,
+    std::list<Cluster>& clusters) {
+  if (cluster_aggregate.count < kMinClusterSize ||
+      cluster_aggregate.send_mean <= TimeDelta::Zero() ||
+      cluster_aggregate.recv_mean <= TimeDelta::Zero()) {
+    return;
+  }
+
+  Cluster cluster;
+  cluster.send_mean = cluster_aggregate.send_mean / cluster_aggregate.count;
+  cluster.recv_mean = cluster_aggregate.recv_mean / cluster_aggregate.count;
+  cluster.mean_size = cluster_aggregate.mean_size / cluster_aggregate.count;
+  cluster.count = cluster_aggregate.count;
+  cluster.num_above_min_delta = cluster_aggregate.num_above_min_delta;
+  clusters.push_back(cluster);
 }
 
 RemoteBitrateEstimatorAbsSendTime::RemoteBitrateEstimatorAbsSendTime(
@@ -96,91 +100,77 @@
     Clock* clock)
     : clock_(clock),
       observer_(observer),
-      inter_arrival_(),
-      estimator_(),
       detector_(&field_trials_),
-      incoming_bitrate_(kBitrateWindowMs, 8000),
-      incoming_bitrate_initialized_(false),
-      total_probes_received_(0),
-      first_packet_time_ms_(-1),
-      last_update_ms_(-1),
-      uma_recorded_(false),
       remote_rate_(&field_trials_) {
   RTC_DCHECK(clock_);
   RTC_DCHECK(observer_);
   RTC_LOG(LS_INFO) << "RemoteBitrateEstimatorAbsSendTime: Instantiating.";
 }
 
-void RemoteBitrateEstimatorAbsSendTime::ComputeClusters(
-    std::list<Cluster>* clusters) const {
-  Cluster current;
-  int64_t prev_send_time = -1;
-  int64_t prev_recv_time = -1;
-  for (std::list<Probe>::const_iterator it = probes_.begin();
-       it != probes_.end(); ++it) {
-    if (prev_send_time >= 0) {
-      int send_delta_ms = it->send_time_ms - prev_send_time;
-      int recv_delta_ms = it->recv_time_ms - prev_recv_time;
-      if (send_delta_ms >= 1 && recv_delta_ms >= 1) {
-        ++current.num_above_min_delta;
+std::list<RemoteBitrateEstimatorAbsSendTime::Cluster>
+RemoteBitrateEstimatorAbsSendTime::ComputeClusters() const {
+  std::list<Cluster> clusters;
+  Cluster cluster_aggregate;
+  Timestamp prev_send_time = Timestamp::MinusInfinity();
+  Timestamp prev_recv_time = Timestamp::MinusInfinity();
+  for (const Probe& probe : probes_) {
+    if (prev_send_time.IsFinite()) {
+      TimeDelta send_delta = probe.send_time - prev_send_time;
+      TimeDelta recv_delta = probe.recv_time - prev_recv_time;
+      if (send_delta >= kMinClusterDelta && recv_delta >= kMinClusterDelta) {
+        ++cluster_aggregate.num_above_min_delta;
       }
-      if (!IsWithinClusterBounds(send_delta_ms, current)) {
-        if (current.count >= kMinClusterSize && current.send_mean_ms > 0.0f &&
-            current.recv_mean_ms > 0.0f) {
-          AddCluster(clusters, &current);
-        }
-        current = Cluster();
+      if (!IsWithinClusterBounds(send_delta, cluster_aggregate)) {
+        MaybeAddCluster(cluster_aggregate, clusters);
+        cluster_aggregate = Cluster();
       }
-      current.send_mean_ms += send_delta_ms;
-      current.recv_mean_ms += recv_delta_ms;
-      current.mean_size += it->payload_size;
-      ++current.count;
+      cluster_aggregate.send_mean += send_delta;
+      cluster_aggregate.recv_mean += recv_delta;
+      cluster_aggregate.mean_size += probe.payload_size;
+      ++cluster_aggregate.count;
     }
-    prev_send_time = it->send_time_ms;
-    prev_recv_time = it->recv_time_ms;
+    prev_send_time = probe.send_time;
+    prev_recv_time = probe.recv_time;
   }
-  if (current.count >= kMinClusterSize && current.send_mean_ms > 0.0f &&
-      current.recv_mean_ms > 0.0f) {
-    AddCluster(clusters, &current);
-  }
+  MaybeAddCluster(cluster_aggregate, clusters);
+  return clusters;
 }
 
-std::list<Cluster>::const_iterator
+const RemoteBitrateEstimatorAbsSendTime::Cluster*
 RemoteBitrateEstimatorAbsSendTime::FindBestProbe(
     const std::list<Cluster>& clusters) const {
-  int highest_probe_bitrate_bps = 0;
-  std::list<Cluster>::const_iterator best_it = clusters.end();
-  for (std::list<Cluster>::const_iterator it = clusters.begin();
-       it != clusters.end(); ++it) {
-    if (it->send_mean_ms == 0 || it->recv_mean_ms == 0)
+  DataRate highest_probe_bitrate = DataRate::Zero();
+  const Cluster* best = nullptr;
+  for (const auto& cluster : clusters) {
+    if (cluster.send_mean == TimeDelta::Zero() ||
+        cluster.recv_mean == TimeDelta::Zero()) {
       continue;
-    if (it->num_above_min_delta > it->count / 2 &&
-        (it->recv_mean_ms - it->send_mean_ms <= 2.0f &&
-         it->send_mean_ms - it->recv_mean_ms <= 5.0f)) {
-      int probe_bitrate_bps =
-          std::min(it->GetSendBitrateBps(), it->GetRecvBitrateBps());
-      if (probe_bitrate_bps > highest_probe_bitrate_bps) {
-        highest_probe_bitrate_bps = probe_bitrate_bps;
-        best_it = it;
+    }
+    if (cluster.num_above_min_delta > cluster.count / 2 &&
+        (cluster.recv_mean - cluster.send_mean <= TimeDelta::Millis(2) &&
+         cluster.send_mean - cluster.recv_mean <= TimeDelta::Millis(5))) {
+      DataRate probe_bitrate =
+          std::min(cluster.SendBitrate(), cluster.RecvBitrate());
+      if (probe_bitrate > highest_probe_bitrate) {
+        highest_probe_bitrate = probe_bitrate;
+        best = &cluster;
       }
     } else {
-      int send_bitrate_bps = it->mean_size * 8 * 1000 / it->send_mean_ms;
-      int recv_bitrate_bps = it->mean_size * 8 * 1000 / it->recv_mean_ms;
-      RTC_LOG(LS_INFO) << "Probe failed, sent at " << send_bitrate_bps
-                       << " bps, received at " << recv_bitrate_bps
-                       << " bps. Mean send delta: " << it->send_mean_ms
-                       << " ms, mean recv delta: " << it->recv_mean_ms
-                       << " ms, num probes: " << it->count;
+      RTC_LOG(LS_INFO) << "Probe failed, sent at "
+                       << cluster.SendBitrate().bps() << " bps, received at "
+                       << cluster.RecvBitrate().bps()
+                       << " bps. Mean send delta: " << cluster.send_mean.ms()
+                       << " ms, mean recv delta: " << cluster.recv_mean.ms()
+                       << " ms, num probes: " << cluster.count;
       break;
     }
   }
-  return best_it;
+  return best;
 }
 
 RemoteBitrateEstimatorAbsSendTime::ProbeResult
-RemoteBitrateEstimatorAbsSendTime::ProcessClusters(int64_t now_ms) {
-  std::list<Cluster> clusters;
-  ComputeClusters(&clusters);
+RemoteBitrateEstimatorAbsSendTime::ProcessClusters(Timestamp now) {
+  std::list<Cluster> clusters = ComputeClusters();
   if (clusters.empty()) {
     // If we reach the max number of probe packets and still have no clusters,
     // we will remove the oldest one.
@@ -189,21 +179,18 @@
     return ProbeResult::kNoUpdate;
   }
 
-  std::list<Cluster>::const_iterator best_it = FindBestProbe(clusters);
-  if (best_it != clusters.end()) {
-    int probe_bitrate_bps =
-        std::min(best_it->GetSendBitrateBps(), best_it->GetRecvBitrateBps());
+  if (const Cluster* best = FindBestProbe(clusters)) {
+    DataRate probe_bitrate = std::min(best->SendBitrate(), best->RecvBitrate());
     // Make sure that a probe sent on a lower bitrate than our estimate can't
     // reduce the estimate.
-    if (IsBitrateImproving(probe_bitrate_bps)) {
+    if (IsBitrateImproving(probe_bitrate)) {
       RTC_LOG(LS_INFO) << "Probe successful, sent at "
-                       << best_it->GetSendBitrateBps() << " bps, received at "
-                       << best_it->GetRecvBitrateBps()
-                       << " bps. Mean send delta: " << best_it->send_mean_ms
-                       << " ms, mean recv delta: " << best_it->recv_mean_ms
-                       << " ms, num probes: " << best_it->count;
-      remote_rate_.SetEstimate(DataRate::BitsPerSec(probe_bitrate_bps),
-                               Timestamp::Millis(now_ms));
+                       << best->SendBitrate().bps() << " bps, received at "
+                       << best->RecvBitrate().bps()
+                       << " bps. Mean send delta: " << best->send_mean.ms()
+                       << " ms, mean recv delta: " << best->recv_mean.ms()
+                       << " ms, num probes: " << best->count;
+      remote_rate_.SetEstimate(probe_bitrate, now);
       return ProbeResult::kBitrateUpdated;
     }
   }
@@ -216,11 +203,11 @@
 }
 
 bool RemoteBitrateEstimatorAbsSendTime::IsBitrateImproving(
-    int new_bitrate_bps) const {
-  bool initial_probe = !remote_rate_.ValidEstimate() && new_bitrate_bps > 0;
-  bool bitrate_above_estimate =
-      remote_rate_.ValidEstimate() &&
-      new_bitrate_bps > remote_rate_.LatestEstimate().bps<int>();
+    DataRate probe_bitrate) const {
+  bool initial_probe =
+      !remote_rate_.ValidEstimate() && probe_bitrate > DataRate::Zero();
+  bool bitrate_above_estimate = remote_rate_.ValidEstimate() &&
+                                probe_bitrate > remote_rate_.LatestEstimate();
   return initial_probe || bitrate_above_estimate;
 }
 
@@ -235,14 +222,15 @@
            "is missing absolute send time extension!";
     return;
   }
-  IncomingPacketInfo(arrival_time_ms, header.extension.absoluteSendTime,
-                     payload_size, header.ssrc);
+  IncomingPacketInfo(Timestamp::Millis(arrival_time_ms),
+                     header.extension.absoluteSendTime,
+                     DataSize::Bytes(payload_size), header.ssrc);
 }
 
 void RemoteBitrateEstimatorAbsSendTime::IncomingPacketInfo(
-    int64_t arrival_time_ms,
+    Timestamp arrival_time,
     uint32_t send_time_24bits,
-    size_t payload_size,
+    DataSize payload_size,
     uint32_t ssrc) {
   RTC_CHECK(send_time_24bits < (1ul << 24));
   if (!uma_recorded_) {
@@ -253,15 +241,16 @@
   // Shift up send time to use the full 32 bits that inter_arrival works with,
   // so wrapping works properly.
   uint32_t timestamp = send_time_24bits << kAbsSendTimeInterArrivalUpshift;
-  int64_t send_time_ms = static_cast<int64_t>(timestamp) * kTimestampToMs;
+  Timestamp send_time =
+      Timestamp::Millis(static_cast<int64_t>(timestamp) * kTimestampToMs);
 
-  int64_t now_ms = clock_->TimeInMilliseconds();
+  Timestamp now = clock_->CurrentTime();
   // TODO(holmer): SSRCs are only needed for REMB, should be broken out from
   // here.
 
   // Check if incoming bitrate estimate is valid, and if it needs to be reset.
   absl::optional<uint32_t> incoming_bitrate =
-      incoming_bitrate_.Rate(arrival_time_ms);
+      incoming_bitrate_.Rate(arrival_time.ms());
   if (incoming_bitrate) {
     incoming_bitrate_initialized_ = true;
   } else if (incoming_bitrate_initialized_) {
@@ -271,74 +260,82 @@
     incoming_bitrate_.Reset();
     incoming_bitrate_initialized_ = false;
   }
-  incoming_bitrate_.Update(payload_size, arrival_time_ms);
+  incoming_bitrate_.Update(payload_size.bytes(), arrival_time.ms());
 
-  if (first_packet_time_ms_ == -1)
-    first_packet_time_ms_ = now_ms;
+  if (first_packet_time_.IsInfinite()) {
+    first_packet_time_ = now;
+  }
 
   uint32_t ts_delta = 0;
   int64_t t_delta = 0;
   int size_delta = 0;
   bool update_estimate = false;
-  uint32_t target_bitrate_bps = 0;
+  DataRate target_bitrate = DataRate::Zero();
   std::vector<uint32_t> ssrcs;
   {
     MutexLock lock(&mutex_);
 
-    TimeoutStreams(now_ms);
-    RTC_DCHECK(inter_arrival_.get());
-    RTC_DCHECK(estimator_.get());
-    ssrcs_[ssrc] = now_ms;
+    TimeoutStreams(now);
+    RTC_DCHECK(inter_arrival_);
+    RTC_DCHECK(estimator_);
+    // TODO(danilchap): Replace 5 lines below with insert_or_assign when that
+    // c++17 function is available.
+    auto inserted = ssrcs_.insert(std::make_pair(ssrc, now));
+    if (!inserted.second) {
+      // Already inserted, update.
+      inserted.first->second = now;
+    }
 
     // For now only try to detect probes while we don't have a valid estimate.
     // We currently assume that only packets larger than 200 bytes are paced by
     // the sender.
-    const size_t kMinProbePacketSize = 200;
+    static constexpr DataSize kMinProbePacketSize = DataSize::Bytes(200);
     if (payload_size > kMinProbePacketSize &&
         (!remote_rate_.ValidEstimate() ||
-         now_ms - first_packet_time_ms_ < kInitialProbingIntervalMs)) {
+         now - first_packet_time_ < kInitialProbingInterval)) {
       // TODO(holmer): Use a map instead to get correct order?
       if (total_probes_received_ < kMaxProbePackets) {
-        int send_delta_ms = -1;
-        int recv_delta_ms = -1;
+        TimeDelta send_delta = TimeDelta::Millis(-1);
+        TimeDelta recv_delta = TimeDelta::Millis(-1);
         if (!probes_.empty()) {
-          send_delta_ms = send_time_ms - probes_.back().send_time_ms;
-          recv_delta_ms = arrival_time_ms - probes_.back().recv_time_ms;
+          send_delta = send_time - probes_.back().send_time;
+          recv_delta = arrival_time - probes_.back().recv_time;
         }
-        RTC_LOG(LS_INFO) << "Probe packet received: send time=" << send_time_ms
-                         << " ms, recv time=" << arrival_time_ms
-                         << " ms, send delta=" << send_delta_ms
-                         << " ms, recv delta=" << recv_delta_ms << " ms.";
+        RTC_LOG(LS_INFO) << "Probe packet received: send time="
+                         << send_time.ms()
+                         << " ms, recv time=" << arrival_time.ms()
+                         << " ms, send delta=" << send_delta.ms()
+                         << " ms, recv delta=" << recv_delta.ms() << " ms.";
       }
-      probes_.push_back(Probe(send_time_ms, arrival_time_ms, payload_size));
+      probes_.emplace_back(send_time, arrival_time, payload_size);
       ++total_probes_received_;
       // Make sure that a probe which updated the bitrate immediately has an
       // effect by calling the OnReceiveBitrateChanged callback.
-      if (ProcessClusters(now_ms) == ProbeResult::kBitrateUpdated)
+      if (ProcessClusters(now) == ProbeResult::kBitrateUpdated)
         update_estimate = true;
     }
-    if (inter_arrival_->ComputeDeltas(timestamp, arrival_time_ms, now_ms,
-                                      payload_size, &ts_delta, &t_delta,
+    if (inter_arrival_->ComputeDeltas(timestamp, arrival_time.ms(), now.ms(),
+                                      payload_size.bytes(), &ts_delta, &t_delta,
                                       &size_delta)) {
       double ts_delta_ms = (1000.0 * ts_delta) / (1 << kInterArrivalShift);
       estimator_->Update(t_delta, ts_delta_ms, size_delta, detector_.State(),
-                         arrival_time_ms);
+                         arrival_time.ms());
       detector_.Detect(estimator_->offset(), ts_delta_ms,
-                       estimator_->num_of_deltas(), arrival_time_ms);
+                       estimator_->num_of_deltas(), arrival_time.ms());
     }
 
     if (!update_estimate) {
       // Check if it's time for a periodic update or if we should update because
       // of an over-use.
-      if (last_update_ms_ == -1 ||
-          now_ms - last_update_ms_ > remote_rate_.GetFeedbackInterval().ms()) {
+      if (last_update_.IsInfinite() ||
+          now.ms() - last_update_.ms() >
+              remote_rate_.GetFeedbackInterval().ms()) {
         update_estimate = true;
       } else if (detector_.State() == BandwidthUsage::kBwOverusing) {
         absl::optional<uint32_t> incoming_rate =
-            incoming_bitrate_.Rate(arrival_time_ms);
+            incoming_bitrate_.Rate(arrival_time.ms());
         if (incoming_rate && remote_rate_.TimeToReduceFurther(
-                                 Timestamp::Millis(now_ms),
-                                 DataRate::BitsPerSec(*incoming_rate))) {
+                                 now, DataRate::BitsPerSec(*incoming_rate))) {
           update_estimate = true;
         }
       }
@@ -349,18 +346,16 @@
       // We also have to update the estimate immediately if we are overusing
       // and the target bitrate is too high compared to what we are receiving.
       const RateControlInput input(
-          detector_.State(),
-          OptionalRateFromOptionalBps(incoming_bitrate_.Rate(arrival_time_ms)));
-      target_bitrate_bps =
-          remote_rate_.Update(&input, Timestamp::Millis(now_ms))
-              .bps<uint32_t>();
+          detector_.State(), OptionalRateFromOptionalBps(
+                                 incoming_bitrate_.Rate(arrival_time.ms())));
+      target_bitrate = remote_rate_.Update(&input, now);
       update_estimate = remote_rate_.ValidEstimate();
       ssrcs = Keys(ssrcs_);
     }
   }
   if (update_estimate) {
-    last_update_ms_ = now_ms;
-    observer_->OnReceiveBitrateChanged(ssrcs, target_bitrate_bps);
+    last_update_ = now;
+    observer_->OnReceiveBitrateChanged(ssrcs, target_bitrate.bps<uint32_t>());
   }
 }
 
@@ -371,9 +366,9 @@
   return kDisabledModuleTime;
 }
 
-void RemoteBitrateEstimatorAbsSendTime::TimeoutStreams(int64_t now_ms) {
-  for (Ssrcs::iterator it = ssrcs_.begin(); it != ssrcs_.end();) {
-    if ((now_ms - it->second) > kStreamTimeOutMs) {
+void RemoteBitrateEstimatorAbsSendTime::TimeoutStreams(Timestamp now) {
+  for (auto it = ssrcs_.begin(); it != ssrcs_.end();) {
+    if (now - it->second > TimeDelta::Millis(kStreamTimeOutMs)) {
       ssrcs_.erase(it++);
     } else {
       ++it;
@@ -381,17 +376,17 @@
   }
   if (ssrcs_.empty()) {
     // We can't update the estimate if we don't have any active streams.
-    inter_arrival_.reset(
-        new InterArrival((kTimestampGroupLengthMs << kInterArrivalShift) / 1000,
-                         kTimestampToMs, true));
-    estimator_.reset(new OveruseEstimator(OverUseDetectorOptions()));
+    inter_arrival_ = std::make_unique<InterArrival>(
+        (kTimestampGroupLengthMs << kInterArrivalShift) / 1000, kTimestampToMs,
+        true);
+    estimator_ = std::make_unique<OveruseEstimator>(OverUseDetectorOptions());
     // We deliberately don't reset the first_packet_time_ms_ here for now since
     // we only probe for bandwidth in the beginning of a call right now.
   }
 }
 
 void RemoteBitrateEstimatorAbsSendTime::OnRttUpdate(int64_t avg_rtt_ms,
-                                                    int64_t max_rtt_ms) {
+                                                    int64_t /*max_rtt_ms*/) {
   MutexLock lock(&mutex_);
   remote_rate_.SetRtt(TimeDelta::Millis(avg_rtt_ms));
 }
diff --git a/modules/remote_bitrate_estimator/remote_bitrate_estimator_abs_send_time.h b/modules/remote_bitrate_estimator/remote_bitrate_estimator_abs_send_time.h
index f42a28f..4117382 100644
--- a/modules/remote_bitrate_estimator/remote_bitrate_estimator_abs_send_time.h
+++ b/modules/remote_bitrate_estimator/remote_bitrate_estimator_abs_send_time.h
@@ -21,6 +21,10 @@
 
 #include "api/rtp_headers.h"
 #include "api/transport/field_trial_based_config.h"
+#include "api/units/data_rate.h"
+#include "api/units/data_size.h"
+#include "api/units/time_delta.h"
+#include "api/units/timestamp.h"
 #include "modules/remote_bitrate_estimator/aimd_rate_control.h"
 #include "modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h"
 #include "modules/remote_bitrate_estimator/inter_arrival.h"
@@ -35,42 +39,6 @@
 
 namespace webrtc {
 
-struct Probe {
-  Probe(int64_t send_time_ms, int64_t recv_time_ms, size_t payload_size)
-      : send_time_ms(send_time_ms),
-        recv_time_ms(recv_time_ms),
-        payload_size(payload_size) {}
-  int64_t send_time_ms;
-  int64_t recv_time_ms;
-  size_t payload_size;
-};
-
-struct Cluster {
-  Cluster()
-      : send_mean_ms(0.0f),
-        recv_mean_ms(0.0f),
-        mean_size(0),
-        count(0),
-        num_above_min_delta(0) {}
-
-  int GetSendBitrateBps() const {
-    RTC_CHECK_GT(send_mean_ms, 0.0f);
-    return mean_size * 8 * 1000 / send_mean_ms;
-  }
-
-  int GetRecvBitrateBps() const {
-    RTC_CHECK_GT(recv_mean_ms, 0.0f);
-    return mean_size * 8 * 1000 / recv_mean_ms;
-  }
-
-  float send_mean_ms;
-  float recv_mean_ms;
-  // TODO(holmer): Add some variance metric as well?
-  size_t mean_size;
-  int count;
-  int num_above_min_delta;
-};
-
 class RemoteBitrateEstimatorAbsSendTime : public RemoteBitrateEstimator {
  public:
   RemoteBitrateEstimatorAbsSendTime(RemoteBitrateObserver* observer,
@@ -100,32 +68,54 @@
   void SetMinBitrate(int min_bitrate_bps) override;
 
  private:
-  typedef std::map<uint32_t, int64_t> Ssrcs;
+  struct Probe {
+    Probe(Timestamp send_time, Timestamp recv_time, DataSize payload_size)
+        : send_time(send_time),
+          recv_time(recv_time),
+          payload_size(payload_size) {}
+
+    Timestamp send_time;
+    Timestamp recv_time;
+    DataSize payload_size;
+  };
+
+  struct Cluster {
+    DataRate SendBitrate() const { return mean_size / send_mean; }
+    DataRate RecvBitrate() const { return mean_size / recv_mean; }
+
+    TimeDelta send_mean = TimeDelta::Zero();
+    TimeDelta recv_mean = TimeDelta::Zero();
+    // TODO(holmer): Add some variance metric as well?
+    DataSize mean_size = DataSize::Zero();
+    int count = 0;
+    int num_above_min_delta = 0;
+  };
+
   enum class ProbeResult { kBitrateUpdated, kNoUpdate };
 
-  static bool IsWithinClusterBounds(int send_delta_ms,
+  static bool IsWithinClusterBounds(TimeDelta send_delta,
                                     const Cluster& cluster_aggregate);
 
-  static void AddCluster(std::list<Cluster>* clusters, Cluster* cluster);
+  static void MaybeAddCluster(const Cluster& cluster_aggregate,
+                              std::list<Cluster>& clusters);
 
-  void IncomingPacketInfo(int64_t arrival_time_ms,
+  void IncomingPacketInfo(Timestamp arrival_time,
                           uint32_t send_time_24bits,
-                          size_t payload_size,
+                          DataSize payload_size,
                           uint32_t ssrc);
 
-  void ComputeClusters(std::list<Cluster>* clusters) const;
+  std::list<Cluster> ComputeClusters() const;
 
-  std::list<Cluster>::const_iterator FindBestProbe(
-      const std::list<Cluster>& clusters) const;
+  const Cluster* FindBestProbe(const std::list<Cluster>& clusters) const;
 
   // Returns true if a probe which changed the estimate was detected.
-  ProbeResult ProcessClusters(int64_t now_ms)
+  ProbeResult ProcessClusters(Timestamp now)
       RTC_EXCLUSIVE_LOCKS_REQUIRED(&mutex_);
 
-  bool IsBitrateImproving(int probe_bitrate_bps) const
+  bool IsBitrateImproving(DataRate probe_bitrate) const
       RTC_EXCLUSIVE_LOCKS_REQUIRED(&mutex_);
 
-  void TimeoutStreams(int64_t now_ms) RTC_EXCLUSIVE_LOCKS_REQUIRED(&mutex_);
+  void TimeoutStreams(Timestamp now) RTC_EXCLUSIVE_LOCKS_REQUIRED(&mutex_);
 
   rtc::RaceChecker network_race_;
   Clock* const clock_;
@@ -134,18 +124,16 @@
   std::unique_ptr<InterArrival> inter_arrival_;
   std::unique_ptr<OveruseEstimator> estimator_;
   OveruseDetector detector_;
-  RateStatistics incoming_bitrate_;
-  bool incoming_bitrate_initialized_;
-  std::vector<int> recent_propagation_delta_ms_;
-  std::vector<int64_t> recent_update_time_ms_;
+  RateStatistics incoming_bitrate_{kBitrateWindowMs, 8000};
+  bool incoming_bitrate_initialized_ = false;
   std::list<Probe> probes_;
-  size_t total_probes_received_;
-  int64_t first_packet_time_ms_;
-  int64_t last_update_ms_;
-  bool uma_recorded_;
+  size_t total_probes_received_ = 0;
+  Timestamp first_packet_time_ = Timestamp::MinusInfinity();
+  Timestamp last_update_ = Timestamp::MinusInfinity();
+  bool uma_recorded_ = false;
 
   mutable Mutex mutex_;
-  Ssrcs ssrcs_ RTC_GUARDED_BY(&mutex_);
+  std::map<uint32_t, Timestamp> ssrcs_ RTC_GUARDED_BY(&mutex_);
   AimdRateControl remote_rate_ RTC_GUARDED_BY(&mutex_);
 };