Revert "Remove FrameBuffer2Proxy"

This reverts commit de0d063767bbaffae7ab9b2c785bb862b387ae5c.

Reason for revert: Perf test regressions that need investigation.

Original change's description:
> Remove FrameBuffer2Proxy
>
> Bug: webrtc:14003
> Change-Id: I461a9159b33ca3693bcb59d94c2035093825588b
> Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/265866
> Commit-Queue: Evan Shrubsole <eshr@webrtc.org>
> Reviewed-by: Erik Språng <sprang@webrtc.org>
> Cr-Commit-Position: refs/heads/main@{#37253}

Bug: webrtc:14003
Change-Id: Ic7ef05e4021e8568eb8cfff13dc3e6753fbdec18
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/266340
Commit-Queue: Evan Shrubsole <eshr@webrtc.org>
Auto-Submit: Evan Shrubsole <eshr@webrtc.org>
Commit-Queue: Erik Språng <sprang@webrtc.org>
Reviewed-by: Erik Språng <sprang@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#37277}
diff --git a/video/BUILD.gn b/video/BUILD.gn
index 6e59619..65f02d8 100644
--- a/video/BUILD.gn
+++ b/video/BUILD.gn
@@ -280,7 +280,6 @@
     "../rtc_base:logging",
     "../rtc_base:macromagic",
     "../rtc_base:rtc_task_queue",
-    "../rtc_base/experiments:rtt_mult_experiment",
     "../system_wrappers",
     "../system_wrappers:field_trial",
   ]
diff --git a/video/frame_buffer_proxy.cc b/video/frame_buffer_proxy.cc
index 1d28d94..f69d9da 100644
--- a/video/frame_buffer_proxy.cc
+++ b/video/frame_buffer_proxy.cc
@@ -21,11 +21,11 @@
 #include "api/video/encoded_frame.h"
 #include "api/video/frame_buffer.h"
 #include "api/video/video_content_type.h"
+#include "modules/video_coding/frame_buffer2.h"
 #include "modules/video_coding/frame_helpers.h"
 #include "modules/video_coding/timing/inter_frame_delay.h"
 #include "modules/video_coding/timing/jitter_estimator.h"
 #include "rtc_base/checks.h"
-#include "rtc_base/experiments/rtt_mult_experiment.h"
 #include "rtc_base/logging.h"
 #include "rtc_base/thread_annotations.h"
 #include "video/frame_decode_timing.h"
@@ -36,6 +36,104 @@
 
 namespace {
 
+class FrameBuffer2Proxy : public FrameBufferProxy {
+ public:
+  FrameBuffer2Proxy(Clock* clock,
+                    VCMTiming* timing,
+                    VCMReceiveStatisticsCallback* stats_proxy,
+                    rtc::TaskQueue* decode_queue,
+                    FrameSchedulingReceiver* receiver,
+                    TimeDelta max_wait_for_keyframe,
+                    TimeDelta max_wait_for_frame,
+                    const FieldTrialsView& field_trials)
+      : max_wait_for_keyframe_(max_wait_for_keyframe),
+        max_wait_for_frame_(max_wait_for_frame),
+        frame_buffer_(clock, timing, stats_proxy, field_trials),
+        decode_queue_(decode_queue),
+        stats_proxy_(stats_proxy),
+        receiver_(receiver) {
+    RTC_DCHECK(decode_queue_);
+    RTC_DCHECK(stats_proxy_);
+    RTC_DCHECK(receiver_);
+  }
+
+  void StopOnWorker() override {
+    RTC_DCHECK_RUN_ON(&worker_sequence_checker_);
+    decode_queue_->PostTask([this] {
+      frame_buffer_.Stop();
+      decode_safety_->SetNotAlive();
+    });
+  }
+
+  void SetProtectionMode(VCMVideoProtection protection_mode) override {
+    RTC_DCHECK_RUN_ON(&worker_sequence_checker_);
+    frame_buffer_.SetProtectionMode(kProtectionNackFEC);
+  }
+
+  void Clear() override {
+    RTC_DCHECK_RUN_ON(&worker_sequence_checker_);
+    frame_buffer_.Clear();
+  }
+
+  absl::optional<int64_t> InsertFrame(
+      std::unique_ptr<EncodedFrame> frame) override {
+    RTC_DCHECK_RUN_ON(&worker_sequence_checker_);
+    int64_t last_continuous_pid = frame_buffer_.InsertFrame(std::move(frame));
+    if (last_continuous_pid != -1)
+      return last_continuous_pid;
+    return absl::nullopt;
+  }
+
+  void UpdateRtt(int64_t max_rtt_ms) override {
+    RTC_DCHECK_RUN_ON(&worker_sequence_checker_);
+    frame_buffer_.UpdateRtt(max_rtt_ms);
+  }
+
+  void StartNextDecode(bool keyframe_required) override {
+    if (!decode_queue_->IsCurrent()) {
+      decode_queue_->PostTask(ToQueuedTask(
+          decode_safety_,
+          [this, keyframe_required] { StartNextDecode(keyframe_required); }));
+      return;
+    }
+    RTC_DCHECK_RUN_ON(decode_queue_);
+
+    frame_buffer_.NextFrame(
+        MaxWait(keyframe_required).ms(), keyframe_required, decode_queue_,
+        /* encoded frame handler */
+        [this, keyframe_required](std::unique_ptr<EncodedFrame> frame) {
+          RTC_DCHECK_RUN_ON(decode_queue_);
+          if (!decode_safety_->alive())
+            return;
+          if (frame) {
+            receiver_->OnEncodedFrame(std::move(frame));
+          } else {
+            receiver_->OnDecodableFrameTimeout(MaxWait(keyframe_required));
+          }
+        });
+  }
+
+  int Size() override {
+    RTC_DCHECK_RUN_ON(&worker_sequence_checker_);
+    return frame_buffer_.Size();
+  }
+
+ private:
+  TimeDelta MaxWait(bool keyframe_required) const {
+    return keyframe_required ? max_wait_for_keyframe_ : max_wait_for_frame_;
+  }
+
+  RTC_NO_UNIQUE_ADDRESS SequenceChecker worker_sequence_checker_;
+  const TimeDelta max_wait_for_keyframe_;
+  const TimeDelta max_wait_for_frame_;
+  video_coding::FrameBuffer frame_buffer_;
+  rtc::TaskQueue* const decode_queue_;
+  VCMReceiveStatisticsCallback* const stats_proxy_;
+  FrameSchedulingReceiver* const receiver_;
+  rtc::scoped_refptr<PendingTaskSafetyFlag> decode_safety_ =
+      PendingTaskSafetyFlag::CreateDetached();
+};
+
 // Max number of frames the buffer will hold.
 static constexpr size_t kMaxFramesBuffered = 800;
 // Max number of decoded frame info that will be saved.
@@ -436,6 +534,7 @@
 };
 
 enum class FrameBufferArm {
+  kFrameBuffer2,
   kFrameBuffer3,
   kSyncDecode,
 };
@@ -444,8 +543,9 @@
 
 FrameBufferArm ParseFrameBufferFieldTrial(const FieldTrialsView& field_trials) {
   webrtc::FieldTrialEnum<FrameBufferArm> arm(
-      "arm", FrameBufferArm::kFrameBuffer3,
+      "arm", FrameBufferArm::kFrameBuffer2,
       {
+          {"FrameBuffer2", FrameBufferArm::kFrameBuffer2},
           {"FrameBuffer3", FrameBufferArm::kFrameBuffer3},
           {"SyncDecoding", FrameBufferArm::kSyncDecode},
       });
@@ -467,6 +567,10 @@
     DecodeSynchronizer* decode_sync,
     const FieldTrialsView& field_trials) {
   switch (ParseFrameBufferFieldTrial(field_trials)) {
+    case FrameBufferArm::kFrameBuffer2:
+      return std::make_unique<FrameBuffer2Proxy>(
+          clock, timing, stats_proxy, decode_queue, receiver,
+          max_wait_for_keyframe, max_wait_for_frame, field_trials);
     case FrameBufferArm::kSyncDecode: {
       std::unique_ptr<FrameDecodeScheduler> scheduler;
       if (decode_sync) {
diff --git a/video/frame_buffer_proxy_unittest.cc b/video/frame_buffer_proxy_unittest.cc
index 4d4aae4..6babcda 100644
--- a/video/frame_buffer_proxy_unittest.cc
+++ b/video/frame_buffer_proxy_unittest.cc
@@ -27,6 +27,7 @@
 #include "api/video/video_content_type.h"
 #include "api/video/video_timing.h"
 #include "rtc_base/checks.h"
+#include "rtc_base/event.h"
 #include "test/fake_encoded_frame.h"
 #include "test/gmock.h"
 #include "test/gtest.h"
@@ -103,6 +104,11 @@
               (override));
 };
 
+bool IsFrameBuffer2Enabled(const FieldTrialsView& field_trials) {
+  return field_trials.Lookup("WebRTC-FrameBuffer3").find("arm:FrameBuffer2") !=
+         std::string::npos;
+}
+
 }  // namespace
 
 constexpr auto kMaxWaitForKeyframe = TimeDelta::Millis(500);
@@ -233,7 +239,7 @@
 
 TEST_P(FrameBufferProxyTest, InitialTimeoutAfterKeyframeTimeoutPeriod) {
   StartNextDecodeForceKeyframe();
-  // No frame inserted. Timeout expected.
+  // No frame insterted. Timeout expected.
   EXPECT_THAT(WaitForFrameOrTimeout(kMaxWaitForKeyframe), TimedOut());
 
   // No new timeout set since receiver has not started new decode.
@@ -658,6 +664,8 @@
 
 TEST_P(FrameBufferProxyTest, FrameCompleteCalledOnceForCompleteTemporalUnit) {
   // FrameBuffer2 logs the complete frame on the arrival of the last layer.
+  if (IsFrameBuffer2Enabled(field_trials_))
+    return;
   StartNextDecodeForceKeyframe();
 
   // `OnCompleteFrame` should not be called for the first two frames since they
@@ -734,13 +742,18 @@
                           .AsLast()
                           .Build());
   // FrameBuffer2 drops the frame, while FrameBuffer3 will continue the stream.
-  EXPECT_THAT(WaitForFrameOrTimeout(kFps30Delay), Frame(test::WithId(2)));
+  if (!IsFrameBuffer2Enabled(field_trials_)) {
+    EXPECT_THAT(WaitForFrameOrTimeout(kFps30Delay), Frame(test::WithId(2)));
+  } else {
+    EXPECT_THAT(WaitForFrameOrTimeout(kMaxWaitForFrame), TimedOut());
+  }
 }
 
 INSTANTIATE_TEST_SUITE_P(
     FrameBufferProxy,
     FrameBufferProxyTest,
-    ::testing::Values("WebRTC-FrameBuffer3/arm:FrameBuffer3/",
+    ::testing::Values("WebRTC-FrameBuffer3/arm:FrameBuffer2/",
+                      "WebRTC-FrameBuffer3/arm:FrameBuffer3/",
                       "WebRTC-FrameBuffer3/arm:SyncDecoding/"));
 
 class LowLatencyFrameBufferProxyTest : public ::testing::Test,
@@ -821,6 +834,8 @@
     FrameBufferProxy,
     LowLatencyFrameBufferProxyTest,
     ::testing::Values(
+        "WebRTC-FrameBuffer3/arm:FrameBuffer2/"
+        "WebRTC-ZeroPlayoutDelay/min_pacing:16ms,max_decode_queue_size:5/",
         "WebRTC-FrameBuffer3/arm:FrameBuffer3/"
         "WebRTC-ZeroPlayoutDelay/min_pacing:16ms,max_decode_queue_size:5/",
         "WebRTC-FrameBuffer3/arm:SyncDecoding/"