[M106] Revert "IOSurfaceCaptureDeviceBase: remove min frame rate logic."

This reverts commit cf915fe4efe335802048d66fa845235ed7e7803a.

Bug: chromium:1371573,chromium:1309653
Change-Id: Ic3183161ad620ad8d6a9b16db3d9c79844a9f6ab
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3959606
Reviewed-by: Mark Foltz <[email protected]>
Commit-Queue: Mark Foltz <[email protected]>
Auto-Submit: Johannes Kron <[email protected]>
Cr-Commit-Position: refs/branch-heads/5249@{#848}
Cr-Branched-From: 4f7bea5de862aaa52e6bde5920755a9ef9db120b-refs/heads/main@{#1036826}
diff --git a/content/browser/media/capture/io_surface_capture_device_base_mac.cc b/content/browser/media/capture/io_surface_capture_device_base_mac.cc
index 36df6df..ec490d38 100644
--- a/content/browser/media/capture/io_surface_capture_device_base_mac.cc
+++ b/content/browser/media/capture/io_surface_capture_device_base_mac.cc
@@ -9,6 +9,23 @@
 
 namespace content {
 
+namespace {
+
+float ComputeMinFrameRate(float requested_frame_rate) {
+  // Set a minimum frame rate of 5 fps, unless the requested frame rate is
+  // even lower.
+  constexpr float kMinFrameRate = 5.f;
+
+  // Don't send frames at more than 80% the requested rate, because doing so
+  // can stochastically toggle between repeated and new frames.
+  constexpr float kRequestedFrameRateFactor = 0.8f;
+
+  return std::min(requested_frame_rate * kRequestedFrameRateFactor,
+                  kMinFrameRate);
+}
+
+}  // namespace
+
 IOSurfaceCaptureDeviceBase::IOSurfaceCaptureDeviceBase() = default;
 IOSurfaceCaptureDeviceBase::~IOSurfaceCaptureDeviceBase() = default;
 
@@ -19,24 +36,20 @@
   DCHECK(client && !client_);
   client_ = std::move(client);
   capture_params_ = params;
+  min_frame_rate_ =
+      ComputeMinFrameRate(capture_params_.requested_format.frame_rate);
 
   OnStart();
 }
 
 void IOSurfaceCaptureDeviceBase::StopAndDeAllocate() {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+  min_frame_rate_enforcement_timer_.reset();
   weak_factory_base_.InvalidateWeakPtrs();
 
   OnStop();
 }
 
-void IOSurfaceCaptureDeviceBase::RequestRefreshFrame() {
-  // Simply send the last received surface, if we ever received one.
-  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
-  if (last_received_io_surface_)
-    SendLastReceivedIOSurfaceToClient();
-}
-
 void IOSurfaceCaptureDeviceBase::OnReceivedIOSurfaceFromStream(
     gfx::ScopedInUseIOSurface io_surface,
     const media::VideoCaptureFormat& capture_format) {
@@ -67,6 +80,16 @@
                                          last_received_capture_format_,
                                          gfx::ColorSpace::CreateREC709()),
       {}, now, now - first_frame_time_);
+
+  // Reset `min_frame_rate_enforcement_timer_`.
+  if (!min_frame_rate_enforcement_timer_) {
+    min_frame_rate_enforcement_timer_ = std::make_unique<base::RepeatingTimer>(
+        FROM_HERE, base::Seconds(1 / min_frame_rate_),
+        base::BindRepeating(
+            &IOSurfaceCaptureDeviceBase::SendLastReceivedIOSurfaceToClient,
+            weak_factory_base_.GetWeakPtr()));
+  }
+  min_frame_rate_enforcement_timer_->Reset();
 }
 
 void IOSurfaceCaptureDeviceBase::ComputeFrameSizeAndDestRect(
diff --git a/content/browser/media/capture/io_surface_capture_device_base_mac.h b/content/browser/media/capture/io_surface_capture_device_base_mac.h
index 3db02755..27f78f7 100644
--- a/content/browser/media/capture/io_surface_capture_device_base_mac.h
+++ b/content/browser/media/capture/io_surface_capture_device_base_mac.h
@@ -29,9 +29,6 @@
   // OnStop is called by StopAndDeAllocate.
   virtual void OnStop() = 0;
 
-  // media::VideoCaptureDevice overrides.
-  void RequestRefreshFrame() override;
-
  protected:
   void OnReceivedIOSurfaceFromStream(
       gfx::ScopedInUseIOSurface io_surface,
@@ -72,6 +69,15 @@
   gfx::ScopedInUseIOSurface last_received_io_surface_;
   media::VideoCaptureFormat last_received_capture_format_;
 
+  // The minimum frame rate.
+  float min_frame_rate_ = 1.f;
+
+  // Timer to enforce `min_frame_rate_` by repeatedly calling
+  // SendLastReceivedIOSurfaceToClient.
+  // TODO(https://crbug.com/1171127): Remove the need for the capture device
+  // to re-submit static content.
+  std::unique_ptr<base::RepeatingTimer> min_frame_rate_enforcement_timer_;
+
   base::WeakPtrFactory<IOSurfaceCaptureDeviceBase> weak_factory_base_{this};
 };