Adds repeating task class.

This CL adds a single class to manage the use case of having a task
that repeats itself by a fixed or variable interval. It replaces the
repeating task previously locally defined for rtp transport controller
send as well as the cancelable periodic task. Furthermore, it is
introduced where one off repeating tasks were created before.

It provides the currently used functionality of the cancelable periodic
task, but not some of the unused features, such as allowing cancellation
of tasks before they are started and cancellation of a task after the
owning task queue has been destroyed.

Bug: webrtc:9883
Change-Id: Ifa7edee836c2a64fce16a7d0f682eb09c879eaca
Reviewed-on: https://webrtc-review.googlesource.com/c/116182
Commit-Queue: Sebastian Jansson <srte@webrtc.org>
Reviewed-by: Karl Wiberg <kwiberg@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#26313}
diff --git a/video/BUILD.gn b/video/BUILD.gn
index f82668a..1b3e698 100644
--- a/video/BUILD.gn
+++ b/video/BUILD.gn
@@ -87,6 +87,7 @@
     "../rtc_base/experiments:alr_experiment",
     "../rtc_base/experiments:quality_scaling_experiment",
     "../rtc_base/system:fallthrough",
+    "../rtc_base/task_utils:repeating_task",
     "../system_wrappers:field_trial",
     "../system_wrappers:metrics",
     "//third_party/abseil-cpp/absl/memory",
@@ -201,6 +202,7 @@
     "../rtc_base:timeutils",
     "../rtc_base/experiments:quality_scaling_experiment",
     "../rtc_base/system:fallthrough",
+    "../rtc_base/task_utils:repeating_task",
     "../system_wrappers:field_trial",
     "//third_party/abseil-cpp/absl/memory",
     "//third_party/abseil-cpp/absl/types:optional",
diff --git a/video/overuse_frame_detector.cc b/video/overuse_frame_detector.cc
index b214b39..510d5e0 100644
--- a/video/overuse_frame_detector.cc
+++ b/video/overuse_frame_detector.cc
@@ -518,43 +518,9 @@
   return instance;
 }
 
-class OveruseFrameDetector::CheckOveruseTask : public rtc::QueuedTask {
- public:
-  CheckOveruseTask(OveruseFrameDetector* overuse_detector,
-                   AdaptationObserverInterface* observer)
-      : overuse_detector_(overuse_detector), observer_(observer) {
-    rtc::TaskQueue::Current()->PostDelayedTask(
-        std::unique_ptr<rtc::QueuedTask>(this), kTimeToFirstCheckForOveruseMs);
-  }
-
-  void Stop() {
-    RTC_CHECK(task_checker_.CalledSequentially());
-    overuse_detector_ = nullptr;
-  }
-
- private:
-  bool Run() override {
-    RTC_CHECK(task_checker_.CalledSequentially());
-    if (!overuse_detector_)
-      return true;  // This will make the task queue delete this task.
-    overuse_detector_->CheckForOveruse(observer_);
-
-    rtc::TaskQueue::Current()->PostDelayedTask(
-        std::unique_ptr<rtc::QueuedTask>(this), kCheckForOveruseIntervalMs);
-    // Return false to prevent this task from being deleted. Ownership has been
-    // transferred to the task queue when PostDelayedTask was called.
-    return false;
-  }
-  rtc::SequencedTaskChecker task_checker_;
-  OveruseFrameDetector* overuse_detector_;
-  // Observer getting overuse reports.
-  AdaptationObserverInterface* observer_;
-};
-
 OveruseFrameDetector::OveruseFrameDetector(
     CpuOveruseMetricsObserver* metrics_observer)
-    : check_overuse_task_(nullptr),
-      metrics_observer_(metrics_observer),
+    : metrics_observer_(metrics_observer),
       num_process_times_(0),
       // TODO(nisse): Use absl::optional
       last_capture_time_us_(-1),
@@ -569,26 +535,25 @@
   task_checker_.Detach();
 }
 
-OveruseFrameDetector::~OveruseFrameDetector() {
-  RTC_DCHECK(!check_overuse_task_) << "StopCheckForOverUse must be called.";
-}
+OveruseFrameDetector::~OveruseFrameDetector() {}
 
 void OveruseFrameDetector::StartCheckForOveruse(
     const CpuOveruseOptions& options,
     AdaptationObserverInterface* overuse_observer) {
   RTC_DCHECK_CALLED_SEQUENTIALLY(&task_checker_);
-  RTC_DCHECK(!check_overuse_task_);
+  RTC_DCHECK(!check_overuse_task_.Running());
   RTC_DCHECK(overuse_observer != nullptr);
 
   SetOptions(options);
-  check_overuse_task_ = new CheckOveruseTask(this, overuse_observer);
+  check_overuse_task_ = RepeatingTaskHandle::DelayedStart(
+      TimeDelta::ms(kTimeToFirstCheckForOveruseMs), [this, overuse_observer] {
+        CheckForOveruse(overuse_observer);
+        return TimeDelta::ms(kCheckForOveruseIntervalMs);
+      });
 }
 void OveruseFrameDetector::StopCheckForOveruse() {
   RTC_DCHECK_CALLED_SEQUENTIALLY(&task_checker_);
-  if (check_overuse_task_) {
-    check_overuse_task_->Stop();
-    check_overuse_task_ = nullptr;
-  }
+  check_overuse_task_.Stop();
 }
 
 void OveruseFrameDetector::EncodedFrameTimeMeasured(int encode_duration_ms) {
diff --git a/video/overuse_frame_detector.h b/video/overuse_frame_detector.h
index 3db8643..d4a2c62 100644
--- a/video/overuse_frame_detector.h
+++ b/video/overuse_frame_detector.h
@@ -21,6 +21,7 @@
 #include "rtc_base/numerics/exp_filter.h"
 #include "rtc_base/sequenced_task_checker.h"
 #include "rtc_base/task_queue.h"
+#include "rtc_base/task_utils/repeating_task.h"
 #include "rtc_base/thread_annotations.h"
 
 namespace webrtc {
@@ -108,8 +109,6 @@
   CpuOveruseOptions options_;
 
  private:
-  class CheckOveruseTask;
-
   void EncodedFrameTimeMeasured(int encode_duration_ms);
   bool IsOverusing(int encode_usage_percent);
   bool IsUnderusing(int encode_usage_percent, int64_t time_now);
@@ -124,7 +123,7 @@
 
   rtc::SequencedTaskChecker task_checker_;
   // Owned by the task queue from where StartCheckForOveruse is called.
-  CheckOveruseTask* check_overuse_task_;
+  RepeatingTaskHandle check_overuse_task_ RTC_GUARDED_BY(task_checker_);
 
   // Stats metrics.
   CpuOveruseMetricsObserver* const metrics_observer_;
diff --git a/video/video_send_stream_impl.cc b/video/video_send_stream_impl.cc
index aa76967..f455d18 100644
--- a/video/video_send_stream_impl.cc
+++ b/video/video_send_stream_impl.cc
@@ -44,6 +44,8 @@
 // Max time we will throttle similar video bitrate allocations.
 static constexpr int64_t kMaxVbaThrottleTimeMs = 500;
 
+constexpr TimeDelta kEncoderTimeOut = TimeDelta::Seconds<2>();
+
 bool TransportSeqNumExtensionConfigured(const VideoSendStream::Config& config) {
   const std::vector<RtpExtension>& extensions = config.rtp.extensions;
   return std::find_if(
@@ -179,58 +181,6 @@
 PacingConfig::PacingConfig(const PacingConfig&) = default;
 PacingConfig::~PacingConfig() = default;
 
-// CheckEncoderActivityTask is used for tracking when the encoder last produced
-// and encoded video frame. If the encoder has not produced anything the last
-// kEncoderTimeOutMs we also want to stop sending padding.
-class VideoSendStreamImpl::CheckEncoderActivityTask : public rtc::QueuedTask {
- public:
-  static const int kEncoderTimeOutMs = 2000;
-  explicit CheckEncoderActivityTask(
-      const rtc::WeakPtr<VideoSendStreamImpl>& send_stream)
-      : activity_(0), send_stream_(std::move(send_stream)), timed_out_(false) {}
-
-  void Stop() {
-    RTC_CHECK(task_checker_.CalledSequentially());
-    send_stream_.reset();
-  }
-
-  void UpdateEncoderActivity() {
-    // UpdateEncoderActivity is called from VideoSendStreamImpl::Encoded on
-    // whatever thread the real encoder implementation run on. In the case of
-    // hardware encoders, there might be several encoders
-    // running in parallel on different threads.
-    rtc::AtomicOps::ReleaseStore(&activity_, 1);
-  }
-
- private:
-  bool Run() override {
-    RTC_CHECK(task_checker_.CalledSequentially());
-    if (!send_stream_)
-      return true;
-    if (!rtc::AtomicOps::AcquireLoad(&activity_)) {
-      if (!timed_out_) {
-        send_stream_->SignalEncoderTimedOut();
-      }
-      timed_out_ = true;
-    } else if (timed_out_) {
-      send_stream_->SignalEncoderActive();
-      timed_out_ = false;
-    }
-    rtc::AtomicOps::ReleaseStore(&activity_, 0);
-
-    rtc::TaskQueue::Current()->PostDelayedTask(
-        std::unique_ptr<rtc::QueuedTask>(this), kEncoderTimeOutMs);
-    // Return false to prevent this task from being deleted. Ownership has been
-    // transferred to the task queue when PostDelayedTask was called.
-    return false;
-  }
-  volatile int activity_;
-
-  rtc::SequencedTaskChecker task_checker_;
-  rtc::WeakPtr<VideoSendStreamImpl> send_stream_;
-  bool timed_out_;
-};
-
 VideoSendStreamImpl::VideoSendStreamImpl(
     SendStatisticsProxy* stats_proxy,
     rtc::TaskQueue* worker_queue,
@@ -254,7 +204,6 @@
       stats_proxy_(stats_proxy),
       config_(config),
       worker_queue_(worker_queue),
-      check_encoder_activity_task_(nullptr),
       call_stats_(call_stats),
       transport_(transport),
       bitrate_allocator_(bitrate_allocator),
@@ -420,12 +369,25 @@
           encoder_bitrate_priority_, has_packet_feedback_});
   // Start monitoring encoder activity.
   {
-    rtc::CritScope lock(&encoder_activity_crit_sect_);
-    RTC_DCHECK(!check_encoder_activity_task_);
-    check_encoder_activity_task_ = new CheckEncoderActivityTask(weak_ptr_);
-    worker_queue_->PostDelayedTask(
-        std::unique_ptr<rtc::QueuedTask>(check_encoder_activity_task_),
-        CheckEncoderActivityTask::kEncoderTimeOutMs);
+    RTC_DCHECK(!check_encoder_activity_task_.Running());
+
+    activity_ = false;
+    timed_out_ = false;
+    check_encoder_activity_task_ =
+        RepeatingTaskHandle::DelayedStart(kEncoderTimeOut, [this] {
+          RTC_DCHECK_RUN_ON(worker_queue_);
+          if (!activity_) {
+            if (!timed_out_) {
+              SignalEncoderTimedOut();
+            }
+            timed_out_ = true;
+          } else if (timed_out_) {
+            SignalEncoderActive();
+            timed_out_ = false;
+          }
+          activity_ = false;
+          return kEncoderTimeOut;
+        });
   }
 
   video_stream_encoder_->SendKeyFrame();
@@ -443,18 +405,14 @@
 
 void VideoSendStreamImpl::StopVideoSendStream() {
   bitrate_allocator_->RemoveObserver(this);
-  {
-    rtc::CritScope lock(&encoder_activity_crit_sect_);
-    check_encoder_activity_task_->Stop();
-    check_encoder_activity_task_ = nullptr;
-  }
+  check_encoder_activity_task_.Stop();
   video_stream_encoder_->OnBitrateUpdated(0, 0, 0);
   stats_proxy_->OnSetEncoderTargetRate(0);
 }
 
 void VideoSendStreamImpl::SignalEncoderTimedOut() {
   RTC_DCHECK_RUN_ON(worker_queue_);
-  // If the encoder has not produced anything the last kEncoderTimeOutMs and it
+  // If the encoder has not produced anything the last kEncoderTimeOut and it
   // is supposed to, deregister as BitrateAllocatorObserver. This can happen
   // if a camera stops producing frames.
   if (encoder_target_rate_bps_ > 0) {
@@ -601,11 +559,9 @@
   // Encoded is called on whatever thread the real encoder implementation run
   // on. In the case of hardware encoders, there might be several encoders
   // running in parallel on different threads.
-  {
-    rtc::CritScope lock(&encoder_activity_crit_sect_);
-    if (check_encoder_activity_task_)
-      check_encoder_activity_task_->UpdateEncoderActivity();
-  }
+
+  // Indicate that there still is activity going on.
+  activity_ = true;
 
   EncodedImageCallback::Result result(EncodedImageCallback::Result::OK);
   if (media_transport_) {
diff --git a/video/video_send_stream_impl.h b/video/video_send_stream_impl.h
index cfc3328..a453228 100644
--- a/video/video_send_stream_impl.h
+++ b/video/video_send_stream_impl.h
@@ -12,6 +12,7 @@
 
 #include <stddef.h>
 #include <stdint.h>
+#include <atomic>
 #include <map>
 #include <memory>
 #include <vector>
@@ -35,6 +36,7 @@
 #include "modules/video_coding/include/video_codec_interface.h"
 #include "rtc_base/critical_section.h"
 #include "rtc_base/task_queue.h"
+#include "rtc_base/task_utils/repeating_task.h"
 #include "rtc_base/thread_annotations.h"
 #include "rtc_base/weak_ptr.h"
 #include "video/call_stats.h"
@@ -107,8 +109,6 @@
   absl::optional<float> configured_pacing_factor_;
 
  private:
-  class CheckEncoderActivityTask;
-
   // Implements BitrateAllocatorObserver.
   uint32_t OnBitrateUpdated(BitrateAllocationUpdate update) override;
 
@@ -131,7 +131,7 @@
   void StartupVideoSendStream();
   // Removes the bitrate observer, stops monitoring and notifies the video
   // encoder of the bitrate update.
-  void StopVideoSendStream();
+  void StopVideoSendStream() RTC_RUN_ON(worker_queue_);
 
   void ConfigureProtection();
   void ConfigureSsrcs();
@@ -146,9 +146,11 @@
 
   rtc::TaskQueue* const worker_queue_;
 
-  rtc::CriticalSection encoder_activity_crit_sect_;
-  CheckEncoderActivityTask* check_encoder_activity_task_
-      RTC_GUARDED_BY(encoder_activity_crit_sect_);
+  RepeatingTaskHandle check_encoder_activity_task_
+      RTC_GUARDED_BY(worker_queue_);
+
+  std::atomic_bool activity_;
+  bool timed_out_ RTC_GUARDED_BY(worker_queue_);
 
   CallStats* const call_stats_;
   RtpTransportControllerSendInterface* const transport_;