Make the callbacks to PollStats for RampUp* tests more regular.

Before I had assumed that it wasn't critical for these tests
to have the stats polled at a very regular interval but the perf
waterfall disagrees, so I'm accounting for drift when scheduling
the callbacks.

Bug: chromium:993688
Change-Id: If7f1d3919093f97508774c0c635fff6fe5081c10
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/149809
Commit-Queue: Tommi <tommi@webrtc.org>
Reviewed-by: Niels Moller <nisse@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#28914}
diff --git a/call/rampup_tests.cc b/call/rampup_tests.cc
index 8f689e7..8aba18d 100644
--- a/call/rampup_tests.cc
+++ b/call/rampup_tests.cc
@@ -23,6 +23,7 @@
 #include "rtc_base/logging.h"
 #include "rtc_base/platform_thread.h"
 #include "rtc_base/string_encode.h"
+#include "rtc_base/time_utils.h"
 #include "test/encoder_settings.h"
 #include "test/field_trial.h"
 #include "test/gtest.h"
@@ -323,6 +324,10 @@
 }
 
 void RampUpTester::PollStats() {
+  RTC_DCHECK_RUN_ON(task_queue_);
+
+  EnsurePollTimeSet();
+
   pending_task_ = -1;
   Call::Stats stats = sender_call_->GetStats();
   EXPECT_GE(expected_bitrate_bps_, 0);
@@ -334,7 +339,7 @@
     observation_complete_.Set();
   } else {
     pending_task_ = task_queue_->PostDelayedTask([this]() { PollStats(); },
-                                                 kPollIntervalMs);
+                                                 GetIntervalForNextPoll());
   }
 }
 
@@ -422,6 +427,22 @@
   TriggerTestDone();
 }
 
+void RampUpTester::EnsurePollTimeSet() {
+  RTC_DCHECK_RUN_ON(task_queue_);
+  if (!next_scheduled_poll_time_ms_)
+    next_scheduled_poll_time_ms_ = rtc::TimeMillis();
+}
+
+int64_t RampUpTester::GetIntervalForNextPoll() {
+  RTC_DCHECK_RUN_ON(task_queue_);
+  RTC_DCHECK_NE(next_scheduled_poll_time_ms_, 0)
+      << "No call to EnsurePollTimeSet()";
+  auto now = rtc::TimeMillis();
+  next_scheduled_poll_time_ms_ += kPollIntervalMs;
+  auto interval = next_scheduled_poll_time_ms_ - now;
+  return interval > 0 ? interval : 0;
+}
+
 RampUpDownUpTester::RampUpDownUpTester(
     size_t num_video_streams,
     size_t num_audio_streams,
@@ -460,6 +481,8 @@
 RampUpDownUpTester::~RampUpDownUpTester() {}
 
 void RampUpDownUpTester::PollStats() {
+  EnsurePollTimeSet();
+
   pending_task_ = -1;
   bool last_round = (test_state_ == kTestEnd);
 
@@ -482,7 +505,7 @@
 
   if (!last_round) {
     pending_task_ = task_queue_->PostDelayedTask([this]() { PollStats(); },
-                                                 kPollIntervalMs);
+                                                 GetIntervalForNextPoll());
   }
 }
 
diff --git a/call/rampup_tests.h b/call/rampup_tests.h
index 9c2f57d..c07c793 100644
--- a/call/rampup_tests.h
+++ b/call/rampup_tests.h
@@ -112,7 +112,21 @@
   std::vector<uint32_t> video_rtx_ssrcs_;
   std::vector<uint32_t> audio_ssrcs_;
 
+  // Initially zero, then set to the target time in milliseconds for when
+  // PollStats() will next be called.
+  int64_t next_scheduled_poll_time_ms_ = 0;
+
  protected:
+  // Call from within PollStats to ensure that initial PollStats() timestamp
+  // is captured.
+  void EnsurePollTimeSet();
+
+  // Calculates the interval from now and until when PollStats() next should be
+  // called. Internally updates a timestamp, so each call will yield the
+  // subsequent timestamp (in milliseconds).
+  // Must be called from the |task_queue_|.
+  int64_t GetIntervalForNextPoll();
+
   test::SingleThreadedTaskQueueForTesting* const task_queue_;
   test::SingleThreadedTaskQueueForTesting::TaskId pending_task_ = -1;
 };