WebRTC-DeprecateGlobalFieldTrialString/Enabled/ - part 10/inf

This patch takes a stab at modules/video_coding,
but reaches only about half.

Bug: webrtc:10335
Change-Id: I0d47d0468b818145470c51ae4e8e75ff58d499ae
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/256112
Reviewed-by: Harald Alvestrand <hta@webrtc.org>
Commit-Queue: Jonas Oreland <jonaso@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#36335}
diff --git a/modules/video_coding/BUILD.gn b/modules/video_coding/BUILD.gn
index 7d6b5da..a328d91 100644
--- a/modules/video_coding/BUILD.gn
+++ b/modules/video_coding/BUILD.gn
@@ -82,6 +82,7 @@
   deps = [
     "..:module_api",
     "../../api:sequence_checker",
+    "../../api:webrtc_key_value_config",
     "../../api/task_queue",
     "../../api/units:time_delta",
     "../../api/units:timestamp",
@@ -93,7 +94,6 @@
     "../../rtc_base/task_utils:pending_task_safety_flag",
     "../../rtc_base/task_utils:repeating_task",
     "../../system_wrappers",
-    "../../system_wrappers:field_trial",
     "../utility",
   ]
 }
@@ -167,11 +167,11 @@
   ]
   deps = [
     ":video_coding_utility",
+    "../../api:webrtc_key_value_config",
     "../../api/units:timestamp",
     "../../api/video:encoded_frame",
     "../../rtc_base:logging",
     "../../rtc_base:rtc_numerics",
-    "../../system_wrappers:field_trial",
   ]
   absl_deps = [
     "//third_party/abseil-cpp/absl/algorithm:container",
@@ -188,6 +188,7 @@
     "timing.h",
   ]
   deps = [
+    "../../api:webrtc_key_value_config",
     "../../api/units:time_delta",
     "../../api/video:video_rtp_headers",
     "../../rtc_base:logging",
@@ -197,7 +198,6 @@
     "../../rtc_base/synchronization:mutex",
     "../../rtc_base/time:timestamp_extrapolator",
     "../../system_wrappers",
-    "../../system_wrappers:field_trial",
   ]
   absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ]
 }
@@ -221,6 +221,7 @@
   ]
   deps = [
     ":rtt_filter",
+    "../../api:webrtc_key_value_config",
     "../../api/units:data_size",
     "../../api/units:frequency",
     "../../api/units:time_delta",
@@ -229,7 +230,6 @@
     "../../rtc_base:safe_conversions",
     "../../rtc_base/experiments:jitter_upper_bound_experiment",
     "../../system_wrappers",
-    "../../system_wrappers:field_trial",
   ]
   absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ]
 }
@@ -314,6 +314,7 @@
     "../../api:rtp_packet_info",
     "../../api:scoped_refptr",
     "../../api:sequence_checker",
+    "../../api:webrtc_key_value_config",
     "../../api/task_queue",
     "../../api/units:data_rate",
     "../../api/units:data_size",
@@ -424,6 +425,8 @@
     "../../api:rtp_headers",
     "../../api:rtp_packet_info",
     "../../api:sequence_checker",
+    "../../api:webrtc_key_value_config",
+    "../../api/transport:field_trial_based_config",
     "../../api/units:timestamp",
     "../../api/video:encoded_image",
     "../../api/video:video_frame",
@@ -436,6 +439,7 @@
     "../../rtc_base:logging",
     "../../rtc_base:rtc_base_approved",
     "../../rtc_base:rtc_event",
+    "../../rtc_base/memory:always_valid_pointer",
     "../../rtc_base/synchronization:mutex",
     "../../system_wrappers",
     "../rtp_rtcp:rtp_rtcp_format",
@@ -497,6 +501,7 @@
     "../../api:array_view",
     "../../api:scoped_refptr",
     "../../api:sequence_checker",
+    "../../api:webrtc_key_value_config",
     "../../api/video:encoded_frame",
     "../../api/video:encoded_image",
     "../../api/video:video_adaptation",
@@ -1233,6 +1238,7 @@
       "../../test:fake_video_codecs",
       "../../test:field_trial",
       "../../test:fileutils",
+      "../../test:scoped_key_value_config",
       "../../test:test_common",
       "../../test:test_support",
       "../../test:video_test_common",
diff --git a/modules/video_coding/deprecated/BUILD.gn b/modules/video_coding/deprecated/BUILD.gn
index a6fa790..9e4b65f 100644
--- a/modules/video_coding/deprecated/BUILD.gn
+++ b/modules/video_coding/deprecated/BUILD.gn
@@ -17,6 +17,7 @@
   deps = [
     "..:nack_requester",
     "../..:module_api",
+    "../../../api:webrtc_key_value_config",
     "../../../api/units:time_delta",
     "../../../api/units:timestamp",
     "../../../rtc_base:checks",
@@ -27,7 +28,6 @@
     "../../../rtc_base/experiments:field_trial_parser",
     "../../../rtc_base/synchronization:mutex",
     "../../../system_wrappers",
-    "../../../system_wrappers:field_trial",
     "../../utility",
   ]
   absl_deps = [ "//third_party/abseil-cpp/absl/base:core_headers" ]
diff --git a/modules/video_coding/deprecated/nack_module.cc b/modules/video_coding/deprecated/nack_module.cc
index 334eb82..4a6ae09 100644
--- a/modules/video_coding/deprecated/nack_module.cc
+++ b/modules/video_coding/deprecated/nack_module.cc
@@ -18,7 +18,6 @@
 #include "rtc_base/checks.h"
 #include "rtc_base/experiments/field_trial_parser.h"
 #include "rtc_base/logging.h"
-#include "system_wrappers/include/field_trial.h"
 
 namespace webrtc {
 
@@ -33,10 +32,9 @@
 const int kNumReorderingBuckets = 10;
 const int kDefaultSendNackDelayMs = 0;
 
-int64_t GetSendNackDelay() {
+int64_t GetSendNackDelay(const WebRtcKeyValueConfig& field_trials) {
   int64_t delay_ms = strtol(
-      webrtc::field_trial::FindFullName("WebRTC-SendNackDelayMs").c_str(),
-      nullptr, 10);
+      field_trials.Lookup("WebRTC-SendNackDelayMs").c_str(), nullptr, 10);
   if (delay_ms > 0 && delay_ms <= 20) {
     RTC_LOG(LS_INFO) << "SendNackDelay is set to " << delay_ms;
     return delay_ms;
@@ -63,7 +61,8 @@
     : min_retry_interval(min_retry), max_rtt(max_rtt), base(base) {}
 
 absl::optional<DEPRECATED_NackModule::BackoffSettings>
-DEPRECATED_NackModule::BackoffSettings::ParseFromFieldTrials() {
+DEPRECATED_NackModule::BackoffSettings::ParseFromFieldTrials(
+    const WebRtcKeyValueConfig& field_trials) {
   // Matches magic number in RTPSender::OnReceivedNack().
   const TimeDelta kDefaultMinRetryInterval = TimeDelta::Millis(5);
   // Upper bound on link-delay considered for exponential backoff.
@@ -79,7 +78,7 @@
   FieldTrialParameter<TimeDelta> max_rtt("max_rtt", kDefaultMaxRtt);
   FieldTrialParameter<double> base("base", kDefaultBase);
   ParseFieldTrial({&enabled, &min_retry, &max_rtt, &base},
-                  field_trial::FindFullName("WebRTC-ExponentialNackBackoff"));
+                  field_trials.Lookup("WebRTC-ExponentialNackBackoff"));
 
   if (enabled) {
     return DEPRECATED_NackModule::BackoffSettings(min_retry.Get(),
@@ -91,7 +90,8 @@
 DEPRECATED_NackModule::DEPRECATED_NackModule(
     Clock* clock,
     NackSender* nack_sender,
-    KeyFrameRequestSender* keyframe_request_sender)
+    KeyFrameRequestSender* keyframe_request_sender,
+    const WebRtcKeyValueConfig& field_trials)
     : clock_(clock),
       nack_sender_(nack_sender),
       keyframe_request_sender_(keyframe_request_sender),
@@ -100,8 +100,8 @@
       rtt_ms_(kDefaultRttMs),
       newest_seq_num_(0),
       next_process_time_ms_(-1),
-      send_nack_delay_ms_(GetSendNackDelay()),
-      backoff_settings_(BackoffSettings::ParseFromFieldTrials()) {
+      send_nack_delay_ms_(GetSendNackDelay(field_trials)),
+      backoff_settings_(BackoffSettings::ParseFromFieldTrials(field_trials)) {
   RTC_DCHECK(clock_);
   RTC_DCHECK(nack_sender_);
   RTC_DCHECK(keyframe_request_sender_);
diff --git a/modules/video_coding/deprecated/nack_module.h b/modules/video_coding/deprecated/nack_module.h
index ec1a688..8d17fff 100644
--- a/modules/video_coding/deprecated/nack_module.h
+++ b/modules/video_coding/deprecated/nack_module.h
@@ -19,6 +19,7 @@
 
 #include "absl/base/attributes.h"
 #include "api/units/time_delta.h"
+#include "api/webrtc_key_value_config.h"
 #include "modules/include/module.h"
 #include "modules/include/module_common_types.h"
 #include "modules/video_coding/histogram.h"
@@ -33,7 +34,8 @@
  public:
   DEPRECATED_NackModule(Clock* clock,
                         NackSender* nack_sender,
-                        KeyFrameRequestSender* keyframe_request_sender);
+                        KeyFrameRequestSender* keyframe_request_sender,
+                        const WebRtcKeyValueConfig& field_trials);
 
   int OnReceivedPacket(uint16_t seq_num, bool is_keyframe);
   int OnReceivedPacket(uint16_t seq_num, bool is_keyframe, bool is_recovered);
@@ -69,7 +71,8 @@
 
   struct BackoffSettings {
     BackoffSettings(TimeDelta min_retry, TimeDelta max_rtt, double base);
-    static absl::optional<BackoffSettings> ParseFromFieldTrials();
+    static absl::optional<BackoffSettings> ParseFromFieldTrials(
+        const WebRtcKeyValueConfig& field_trials);
 
     // Min time between nacks.
     const TimeDelta min_retry_interval;
diff --git a/modules/video_coding/frame_buffer2.cc b/modules/video_coding/frame_buffer2.cc
index b4b9c11..bfa3b36 100644
--- a/modules/video_coding/frame_buffer2.cc
+++ b/modules/video_coding/frame_buffer2.cc
@@ -33,7 +33,6 @@
 #include "rtc_base/numerics/sequence_number_util.h"
 #include "rtc_base/trace_event.h"
 #include "system_wrappers/include/clock.h"
-#include "system_wrappers/include/field_trial.h"
 
 namespace webrtc {
 namespace video_coding {
@@ -58,11 +57,12 @@
 
 FrameBuffer::FrameBuffer(Clock* clock,
                          VCMTiming* timing,
-                         VCMReceiveStatisticsCallback* stats_callback)
+                         VCMReceiveStatisticsCallback* stats_callback,
+                         const WebRtcKeyValueConfig& field_trials)
     : decoded_frames_history_(kMaxFramesHistory),
       clock_(clock),
       callback_queue_(nullptr),
-      jitter_estimator_(clock),
+      jitter_estimator_(clock, field_trials),
       timing_(timing),
       stopped_(false),
       protection_mode_(kProtectionNack),
@@ -73,7 +73,7 @@
           "max_decode_queue_size",
           kZeroPlayoutDelayDefaultMaxDecodeQueueSize) {
   ParseFieldTrial({&zero_playout_delay_max_decode_queue_size_},
-                  field_trial::FindFullName("WebRTC-ZeroPlayoutDelay"));
+                  field_trials.Lookup("WebRTC-ZeroPlayoutDelay"));
   callback_checker_.Detach();
 }
 
diff --git a/modules/video_coding/frame_buffer2.h b/modules/video_coding/frame_buffer2.h
index 5cefa8b..cd4cbcd 100644
--- a/modules/video_coding/frame_buffer2.h
+++ b/modules/video_coding/frame_buffer2.h
@@ -20,6 +20,7 @@
 #include "absl/container/inlined_vector.h"
 #include "api/sequence_checker.h"
 #include "api/video/encoded_frame.h"
+#include "api/webrtc_key_value_config.h"
 #include "modules/video_coding/include/video_coding_defines.h"
 #include "modules/video_coding/inter_frame_delay.h"
 #include "modules/video_coding/jitter_estimator.h"
@@ -47,7 +48,8 @@
  public:
   FrameBuffer(Clock* clock,
               VCMTiming* timing,
-              VCMReceiveStatisticsCallback* stats_callback);
+              VCMReceiveStatisticsCallback* stats_callback,
+              const WebRtcKeyValueConfig& field_trials);
 
   FrameBuffer() = delete;
   FrameBuffer(const FrameBuffer&) = delete;
diff --git a/modules/video_coding/frame_buffer2_unittest.cc b/modules/video_coding/frame_buffer2_unittest.cc
index d8ba863..b0e3f1d 100644
--- a/modules/video_coding/frame_buffer2_unittest.cc
+++ b/modules/video_coding/frame_buffer2_unittest.cc
@@ -28,6 +28,7 @@
 #include "test/field_trial.h"
 #include "test/gmock.h"
 #include "test/gtest.h"
+#include "test/scoped_key_value_config.h"
 #include "test/time_controller/simulated_time_controller.h"
 
 using ::testing::_;
@@ -40,7 +41,8 @@
 
 class VCMTimingFake : public VCMTiming {
  public:
-  explicit VCMTimingFake(Clock* clock) : VCMTiming(clock) {}
+  explicit VCMTimingFake(Clock* clock, const WebRtcKeyValueConfig& field_trials)
+      : VCMTiming(clock, field_trials) {}
 
   Timestamp RenderTime(uint32_t frame_timestamp, Timestamp now) const override {
     if (last_render_time_.IsMinusInfinity()) {
@@ -131,10 +133,11 @@
             time_controller_.GetTaskQueueFactory()->CreateTaskQueue(
                 "extract queue",
                 TaskQueueFactory::Priority::NORMAL)),
-        timing_(time_controller_.GetClock()),
+        timing_(time_controller_.GetClock(), field_trials_),
         buffer_(new FrameBuffer(time_controller_.GetClock(),
                                 &timing_,
-                                &stats_callback_)),
+                                &stats_callback_,
+                                field_trials_)),
         rand_(0x34678213) {}
 
   template <typename... T>
@@ -213,6 +216,7 @@
 
   uint32_t Rand() { return rand_.Rand<uint32_t>(); }
 
+  test::ScopedKeyValueConfig field_trials_;
   webrtc::GlobalSimulatedTimeController time_controller_;
   rtc::TaskQueue time_task_queue_;
   VCMTimingFake timing_;
@@ -276,9 +280,10 @@
 }
 
 TEST_F(TestFrameBuffer2, ZeroPlayoutDelay) {
-  VCMTiming timing(time_controller_.GetClock());
-  buffer_.reset(
-      new FrameBuffer(time_controller_.GetClock(), &timing, &stats_callback_));
+  test::ScopedKeyValueConfig field_trials;
+  VCMTiming timing(time_controller_.GetClock(), field_trials);
+  buffer_.reset(new FrameBuffer(time_controller_.GetClock(), &timing,
+                                &stats_callback_, field_trials));
   const VideoPlayoutDelay kPlayoutDelayMs = {0, 0};
   std::unique_ptr<FrameObjectFake> test_frame(new FrameObjectFake());
   test_frame->SetId(0);
diff --git a/modules/video_coding/frame_buffer3.cc b/modules/video_coding/frame_buffer3.cc
index d02a997..7be5ffa 100644
--- a/modules/video_coding/frame_buffer3.cc
+++ b/modules/video_coding/frame_buffer3.cc
@@ -19,7 +19,6 @@
 #include "absl/container/inlined_vector.h"
 #include "rtc_base/logging.h"
 #include "rtc_base/numerics/sequence_number_util.h"
-#include "system_wrappers/include/field_trial.h"
 
 namespace webrtc {
 namespace {
@@ -63,9 +62,11 @@
 }
 }  // namespace
 
-FrameBuffer::FrameBuffer(int max_size, int max_decode_history)
+FrameBuffer::FrameBuffer(int max_size,
+                         int max_decode_history,
+                         const WebRtcKeyValueConfig& field_trials)
     : legacy_frame_id_jump_behavior_(
-          !field_trial::IsDisabled("WebRTC-LegacyFrameIdJumpBehavior")),
+          !field_trials.IsDisabled("WebRTC-LegacyFrameIdJumpBehavior")),
       max_size_(max_size),
       decoded_frame_history_(max_decode_history) {}
 
diff --git a/modules/video_coding/frame_buffer3.h b/modules/video_coding/frame_buffer3.h
index 1f3f71a..9683195 100644
--- a/modules/video_coding/frame_buffer3.h
+++ b/modules/video_coding/frame_buffer3.h
@@ -19,6 +19,7 @@
 #include "absl/types/optional.h"
 #include "api/units/timestamp.h"
 #include "api/video/encoded_frame.h"
+#include "api/webrtc_key_value_config.h"
 #include "modules/video_coding/utility/decoded_frames_history.h"
 
 namespace webrtc {
@@ -33,7 +34,10 @@
   // The `max_size` determines the maxmimum number of frames the buffer will
   // store, and max_decode_history determines how far back (by frame ID) the
   // buffer will store if a frame was decoded or not.
-  FrameBuffer(int max_size, int max_decode_history);
+  FrameBuffer(int max_size,
+              int max_decode_history,
+              // TODO(hta): remove field trials!
+              const WebRtcKeyValueConfig& field_trials);
   FrameBuffer(const FrameBuffer&) = delete;
   FrameBuffer& operator=(const FrameBuffer&) = delete;
   ~FrameBuffer() = default;
diff --git a/modules/video_coding/frame_buffer3_unittest.cc b/modules/video_coding/frame_buffer3_unittest.cc
index b70cd14..27a25f2 100644
--- a/modules/video_coding/frame_buffer3_unittest.cc
+++ b/modules/video_coding/frame_buffer3_unittest.cc
@@ -15,6 +15,7 @@
 #include "test/field_trial.h"
 #include "test/gmock.h"
 #include "test/gtest.h"
+#include "test/scoped_key_value_config.h"
 
 namespace webrtc {
 namespace {
@@ -79,7 +80,9 @@
 };
 
 TEST(FrameBuffer3Test, RejectInvalidRefs) {
-  FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100);
+  test::ScopedKeyValueConfig field_trials;
+  FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100,
+                     field_trials);
   // Ref must be less than the id of this frame.
   buffer.InsertFrame(Builder().Time(0).Id(0).Refs({0}).AsLast().Build());
   EXPECT_THAT(buffer.LastContinuousFrameId(), Eq(absl::nullopt));
@@ -91,7 +94,9 @@
 }
 
 TEST(FrameBuffer3Test, LastContinuousUpdatesOnInsertedFrames) {
-  FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100);
+  test::ScopedKeyValueConfig field_trials;
+  FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100,
+                     field_trials);
   EXPECT_THAT(buffer.LastContinuousFrameId(), Eq(absl::nullopt));
   EXPECT_THAT(buffer.LastContinuousTemporalUnitFrameId(), Eq(absl::nullopt));
 
@@ -105,7 +110,9 @@
 }
 
 TEST(FrameBuffer3Test, LastContinuousFrameReordering) {
-  FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100);
+  test::ScopedKeyValueConfig field_trials;
+  FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100,
+                     field_trials);
 
   buffer.InsertFrame(Builder().Time(10).Id(1).AsLast().Build());
   buffer.InsertFrame(Builder().Time(30).Id(3).Refs({2}).AsLast().Build());
@@ -116,7 +123,9 @@
 }
 
 TEST(FrameBuffer3Test, LastContinuousTemporalUnit) {
-  FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100);
+  test::ScopedKeyValueConfig field_trials;
+  FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100,
+                     field_trials);
 
   buffer.InsertFrame(Builder().Time(10).Id(1).Build());
   EXPECT_THAT(buffer.LastContinuousTemporalUnitFrameId(), Eq(absl::nullopt));
@@ -125,7 +134,9 @@
 }
 
 TEST(FrameBuffer3Test, LastContinuousTemporalUnitReordering) {
-  FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100);
+  test::ScopedKeyValueConfig field_trials;
+  FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100,
+                     field_trials);
 
   buffer.InsertFrame(Builder().Time(10).Id(1).Build());
   buffer.InsertFrame(Builder().Time(20).Id(3).Refs({1}).Build());
@@ -137,7 +148,9 @@
 }
 
 TEST(FrameBuffer3Test, NextDecodable) {
-  FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100);
+  test::ScopedKeyValueConfig field_trials;
+  FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100,
+                     field_trials);
 
   EXPECT_THAT(buffer.NextDecodableTemporalUnitRtpTimestamp(),
               Eq(absl::nullopt));
@@ -146,7 +159,9 @@
 }
 
 TEST(FrameBuffer3Test, AdvanceNextDecodableOnExtraction) {
-  FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100);
+  test::ScopedKeyValueConfig field_trials;
+  FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100,
+                     field_trials);
 
   buffer.InsertFrame(Builder().Time(10).Id(1).AsLast().Build());
   buffer.InsertFrame(Builder().Time(20).Id(2).AsLast().Build());
@@ -164,7 +179,9 @@
 }
 
 TEST(FrameBuffer3Test, AdvanceLastDecodableOnExtraction) {
-  FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100);
+  test::ScopedKeyValueConfig field_trials;
+  FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100,
+                     field_trials);
 
   buffer.InsertFrame(Builder().Time(10).Id(1).AsLast().Build());
   buffer.InsertFrame(Builder().Time(20).Id(2).Refs({1}).AsLast().Build());
@@ -177,7 +194,9 @@
 }
 
 TEST(FrameBuffer3Test, FrameUpdatesNextDecodable) {
-  FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100);
+  test::ScopedKeyValueConfig field_trials;
+  FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100,
+                     field_trials);
 
   buffer.InsertFrame(Builder().Time(20).Id(2).AsLast().Build());
   EXPECT_THAT(buffer.NextDecodableTemporalUnitRtpTimestamp(), Eq(20U));
@@ -187,7 +206,9 @@
 }
 
 TEST(FrameBuffer3Test, KeyframeClearsFullBuffer) {
-  FrameBuffer buffer(/*max_frame_slots=*/5, /*max_decode_history=*/10);
+  test::ScopedKeyValueConfig field_trials;
+  FrameBuffer buffer(/*max_frame_slots=*/5, /*max_decode_history=*/10,
+                     field_trials);
   buffer.InsertFrame(Builder().Time(10).Id(1).AsLast().Build());
   buffer.InsertFrame(Builder().Time(20).Id(2).Refs({1}).AsLast().Build());
   buffer.InsertFrame(Builder().Time(30).Id(3).Refs({2}).AsLast().Build());
@@ -204,7 +225,9 @@
 }
 
 TEST(FrameBuffer3Test, DropNextDecodableTemporalUnit) {
-  FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100);
+  test::ScopedKeyValueConfig field_trials;
+  FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100,
+                     field_trials);
   buffer.InsertFrame(Builder().Time(10).Id(1).AsLast().Build());
   buffer.InsertFrame(Builder().Time(20).Id(2).Refs({1}).AsLast().Build());
   buffer.InsertFrame(Builder().Time(30).Id(3).Refs({1}).AsLast().Build());
@@ -216,7 +239,9 @@
 }
 
 TEST(FrameBuffer3Test, OldFramesAreIgnored) {
-  FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100);
+  test::ScopedKeyValueConfig field_trials;
+  FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100,
+                     field_trials);
   buffer.InsertFrame(Builder().Time(10).Id(1).AsLast().Build());
   buffer.InsertFrame(Builder().Time(20).Id(2).Refs({1}).AsLast().Build());
 
@@ -232,7 +257,9 @@
 }
 
 TEST(FrameBuffer3Test, ReturnFullTemporalUnitKSVC) {
-  FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100);
+  test::ScopedKeyValueConfig field_trials;
+  FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100,
+                     field_trials);
   buffer.InsertFrame(Builder().Time(10).Id(1).Build());
   buffer.InsertFrame(Builder().Time(10).Id(2).Refs({1}).Build());
   buffer.InsertFrame(Builder().Time(10).Id(3).Refs({2}).AsLast().Build());
@@ -245,7 +272,9 @@
 }
 
 TEST(FrameBuffer3Test, InterleavedStream) {
-  FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100);
+  test::ScopedKeyValueConfig field_trials;
+  FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100,
+                     field_trials);
   buffer.InsertFrame(Builder().Time(10).Id(1).AsLast().Build());
   buffer.InsertFrame(Builder().Time(20).Id(2).Refs({1}).AsLast().Build());
   buffer.InsertFrame(Builder().Time(30).Id(3).Refs({1}).AsLast().Build());
@@ -275,9 +304,10 @@
 
 TEST(FrameBuffer3Test, LegacyFrameIdJumpBehavior) {
   {
-    test::ScopedFieldTrials field_trial(
+    test::ScopedKeyValueConfig field_trials(
         "WebRTC-LegacyFrameIdJumpBehavior/Disabled/");
-    FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100);
+    FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100,
+                       field_trials);
 
     buffer.InsertFrame(Builder().Time(20).Id(3).AsLast().Build());
     EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(),
@@ -288,7 +318,9 @@
 
   {
     // WebRTC-LegacyFrameIdJumpBehavior is disabled by default.
-    FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100);
+    test::ScopedKeyValueConfig field_trials;
+    FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100,
+                       field_trials);
 
     buffer.InsertFrame(Builder().Time(20).Id(3).AsLast().Build());
     EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(),
@@ -302,7 +334,9 @@
 }
 
 TEST(FrameBuffer3Test, TotalNumberOfContinuousTemporalUnits) {
-  FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100);
+  test::ScopedKeyValueConfig field_trials;
+  FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100,
+                     field_trials);
   EXPECT_THAT(buffer.GetTotalNumberOfContinuousTemporalUnits(), Eq(0));
 
   buffer.InsertFrame(Builder().Time(10).Id(1).AsLast().Build());
@@ -321,7 +355,9 @@
 }
 
 TEST(FrameBuffer3Test, TotalNumberOfDroppedFrames) {
-  FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100);
+  test::ScopedKeyValueConfig field_trials;
+  FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100,
+                     field_trials);
   EXPECT_THAT(buffer.GetTotalNumberOfDroppedFrames(), Eq(0));
 
   buffer.InsertFrame(Builder().Time(10).Id(1).AsLast().Build());
diff --git a/modules/video_coding/generic_decoder.cc b/modules/video_coding/generic_decoder.cc
index 4b55f85b..78d77d3 100644
--- a/modules/video_coding/generic_decoder.cc
+++ b/modules/video_coding/generic_decoder.cc
@@ -23,12 +23,13 @@
 #include "rtc_base/time_utils.h"
 #include "rtc_base/trace_event.h"
 #include "system_wrappers/include/clock.h"
-#include "system_wrappers/include/field_trial.h"
 
 namespace webrtc {
 
-VCMDecodedFrameCallback::VCMDecodedFrameCallback(VCMTiming* timing,
-                                                 Clock* clock)
+VCMDecodedFrameCallback::VCMDecodedFrameCallback(
+    VCMTiming* timing,
+    Clock* clock,
+    const WebRtcKeyValueConfig& field_trials)
     : _clock(clock),
       _timing(timing),
       _timestampMap(kDecoderFrameMemoryLength),
@@ -40,10 +41,10 @@
       _clock->CurrentNtpInMilliseconds() - _clock->TimeInMilliseconds();
 
   ParseFieldTrial({&_extra_decode_time},
-                  field_trial::FindFullName("WebRTC-SlowDownDecoder"));
+                  field_trials.Lookup("WebRTC-SlowDownDecoder"));
   ParseFieldTrial({&low_latency_renderer_enabled_,
                    &low_latency_renderer_include_predecode_buffer_},
-                  field_trial::FindFullName("WebRTC-LowLatencyRenderer"));
+                  field_trials.Lookup("WebRTC-LowLatencyRenderer"));
 }
 
 VCMDecodedFrameCallback::~VCMDecodedFrameCallback() {}
diff --git a/modules/video_coding/generic_decoder.h b/modules/video_coding/generic_decoder.h
index 31d8460..34f22c4 100644
--- a/modules/video_coding/generic_decoder.h
+++ b/modules/video_coding/generic_decoder.h
@@ -16,6 +16,7 @@
 #include "api/sequence_checker.h"
 #include "api/units/time_delta.h"
 #include "api/video_codecs/video_decoder.h"
+#include "api/webrtc_key_value_config.h"
 #include "modules/video_coding/encoded_frame.h"
 #include "modules/video_coding/include/video_codec_interface.h"
 #include "modules/video_coding/timestamp_map.h"
@@ -31,7 +32,9 @@
 
 class VCMDecodedFrameCallback : public DecodedImageCallback {
  public:
-  VCMDecodedFrameCallback(VCMTiming* timing, Clock* clock);
+  VCMDecodedFrameCallback(VCMTiming* timing,
+                          Clock* clock,
+                          const WebRtcKeyValueConfig& field_trials);
   ~VCMDecodedFrameCallback() override;
   void SetUserReceiveCallback(VCMReceiveCallback* receiveCallback);
   VCMReceiveCallback* UserReceiveCallback();
diff --git a/modules/video_coding/generic_decoder_unittest.cc b/modules/video_coding/generic_decoder_unittest.cc
index 466459e..d9ca8c6 100644
--- a/modules/video_coding/generic_decoder_unittest.cc
+++ b/modules/video_coding/generic_decoder_unittest.cc
@@ -24,6 +24,7 @@
 #include "test/fake_decoder.h"
 #include "test/gmock.h"
 #include "test/gtest.h"
+#include "test/scoped_key_value_config.h"
 
 namespace webrtc {
 namespace video_coding {
@@ -66,10 +67,10 @@
  protected:
   GenericDecoderTest()
       : clock_(0),
-        timing_(&clock_),
+        timing_(&clock_, field_trials_),
         task_queue_factory_(CreateDefaultTaskQueueFactory()),
         decoder_(task_queue_factory_.get()),
-        vcm_callback_(&timing_, &clock_),
+        vcm_callback_(&timing_, &clock_, field_trials_),
         generic_decoder_(&decoder_) {}
 
   void SetUp() override {
@@ -82,6 +83,7 @@
     generic_decoder_.Configure(settings);
   }
 
+  test::ScopedKeyValueConfig field_trials_;
   SimulatedClock clock_;
   VCMTiming timing_;
   std::unique_ptr<TaskQueueFactory> task_queue_factory_;
diff --git a/modules/video_coding/include/video_coding.h b/modules/video_coding/include/video_coding.h
index 77b3eac..8cedc4a 100644
--- a/modules/video_coding/include/video_coding.h
+++ b/modules/video_coding/include/video_coding.h
@@ -13,6 +13,7 @@
 
 #include "api/video/video_frame.h"
 #include "api/video_codecs/video_decoder.h"
+#include "api/webrtc_key_value_config.h"
 #include "modules/include/module.h"
 #include "modules/rtp_rtcp/source/rtp_video_header.h"
 #include "modules/video_coding/include/video_coding_defines.h"
@@ -28,7 +29,9 @@
 class VideoCodingModule : public Module {
  public:
   // DEPRECATED.
-  static VideoCodingModule* Create(Clock* clock);
+  static VideoCodingModule* Create(
+      Clock* clock,
+      const WebRtcKeyValueConfig* field_trials = nullptr);
 
   /*
    *   Receiver
diff --git a/modules/video_coding/jitter_buffer.cc b/modules/video_coding/jitter_buffer.cc
index f51b6ec..5983bc1 100644
--- a/modules/video_coding/jitter_buffer.cc
+++ b/modules/video_coding/jitter_buffer.cc
@@ -109,7 +109,8 @@
 }
 
 VCMJitterBuffer::VCMJitterBuffer(Clock* clock,
-                                 std::unique_ptr<EventWrapper> event)
+                                 std::unique_ptr<EventWrapper> event,
+                                 const WebRtcKeyValueConfig& field_trials)
     : clock_(clock),
       running_(false),
       frame_event_(std::move(event)),
@@ -122,7 +123,7 @@
       num_consecutive_old_packets_(0),
       num_packets_(0),
       num_duplicated_packets_(0),
-      jitter_estimate_(clock),
+      jitter_estimate_(clock, field_trials),
       missing_sequence_numbers_(SequenceNumberLessThan()),
       latest_received_sequence_number_(0),
       max_nack_list_size_(0),
diff --git a/modules/video_coding/jitter_buffer.h b/modules/video_coding/jitter_buffer.h
index df7581a..70e65be 100644
--- a/modules/video_coding/jitter_buffer.h
+++ b/modules/video_coding/jitter_buffer.h
@@ -17,6 +17,7 @@
 #include <set>
 #include <vector>
 
+#include "api/webrtc_key_value_config.h"
 #include "modules/include/module_common_types.h"
 #include "modules/include/module_common_types_public.h"
 #include "modules/video_coding/decoding_state.h"
@@ -69,7 +70,9 @@
 
 class VCMJitterBuffer {
  public:
-  VCMJitterBuffer(Clock* clock, std::unique_ptr<EventWrapper> event);
+  VCMJitterBuffer(Clock* clock,
+                  std::unique_ptr<EventWrapper> event,
+                  const WebRtcKeyValueConfig& field_trials);
 
   ~VCMJitterBuffer();
 
diff --git a/modules/video_coding/jitter_buffer_unittest.cc b/modules/video_coding/jitter_buffer_unittest.cc
index 801eeb6..930eca5 100644
--- a/modules/video_coding/jitter_buffer_unittest.cc
+++ b/modules/video_coding/jitter_buffer_unittest.cc
@@ -23,11 +23,10 @@
 #include "modules/video_coding/test/stream_generator.h"
 #include "rtc_base/location.h"
 #include "system_wrappers/include/clock.h"
-#include "system_wrappers/include/field_trial.h"
 #include "system_wrappers/include/metrics.h"
-#include "test/field_trial.h"
 #include "test/gmock.h"
 #include "test/gtest.h"
+#include "test/scoped_key_value_config.h"
 
 namespace webrtc {
 
@@ -37,7 +36,7 @@
   void SetUp() override {
     clock_.reset(new SimulatedClock(0));
     jitter_buffer_.reset(new VCMJitterBuffer(
-        clock_.get(), absl::WrapUnique(EventWrapper::Create())));
+        clock_.get(), absl::WrapUnique(EventWrapper::Create()), field_trials_));
     jitter_buffer_->Start();
     seq_num_ = 1234;
     timestamp_ = 0;
@@ -118,6 +117,7 @@
   uint32_t timestamp_;
   int size_;
   uint8_t data_[1500];
+  test::ScopedKeyValueConfig field_trials_;
   std::unique_ptr<VCMPacket> packet_;
   std::unique_ptr<SimulatedClock> clock_;
   std::unique_ptr<VCMJitterBuffer> jitter_buffer_;
@@ -132,7 +132,7 @@
     max_nack_list_size_ = 150;
     oldest_packet_to_nack_ = 250;
     jitter_buffer_ = new VCMJitterBuffer(
-        clock_.get(), absl::WrapUnique(EventWrapper::Create()));
+        clock_.get(), absl::WrapUnique(EventWrapper::Create()), field_trials_);
     stream_generator_ = new StreamGenerator(0, clock_->TimeInMilliseconds());
     jitter_buffer_->Start();
     jitter_buffer_->SetNackSettings(max_nack_list_size_, oldest_packet_to_nack_,
@@ -212,6 +212,7 @@
     return ret;
   }
 
+  test::ScopedKeyValueConfig field_trials_;
   VCMJitterBuffer* jitter_buffer_;
   StreamGenerator* stream_generator_;
   std::unique_ptr<SimulatedClock> clock_;
diff --git a/modules/video_coding/jitter_estimator.cc b/modules/video_coding/jitter_estimator.cc
index 5ecd545..e38dfaa 100644
--- a/modules/video_coding/jitter_estimator.cc
+++ b/modules/video_coding/jitter_estimator.cc
@@ -21,11 +21,11 @@
 #include "api/units/frequency.h"
 #include "api/units/time_delta.h"
 #include "api/units/timestamp.h"
+#include "api/webrtc_key_value_config.h"
 #include "modules/video_coding/rtt_filter.h"
 #include "rtc_base/experiments/jitter_upper_bound_experiment.h"
 #include "rtc_base/numerics/safe_conversions.h"
 #include "system_wrappers/include/clock.h"
-#include "system_wrappers/include/field_trial.h"
 
 namespace webrtc {
 namespace {
@@ -49,14 +49,15 @@
 
 }  // namespace
 
-VCMJitterEstimator::VCMJitterEstimator(Clock* clock)
+VCMJitterEstimator::VCMJitterEstimator(Clock* clock,
+                                       const WebRtcKeyValueConfig& field_trials)
     : fps_counter_(30),  // TODO(sprang): Use an estimator with limit based on
                          // time, rather than number of samples.
       time_deviation_upper_bound_(
           JitterUpperBoundExperiment::GetUpperBoundSigmas().value_or(
               kDefaultMaxTimestampDeviationInSigmas)),
       enable_reduced_delay_(
-          !field_trial::IsEnabled("WebRTC-ReducedJitterDelayKillSwitch")),
+          !field_trials.IsEnabled("WebRTC-ReducedJitterDelayKillSwitch")),
       clock_(clock) {
   Reset();
 }
diff --git a/modules/video_coding/jitter_estimator.h b/modules/video_coding/jitter_estimator.h
index 026fb7e..9672d88 100644
--- a/modules/video_coding/jitter_estimator.h
+++ b/modules/video_coding/jitter_estimator.h
@@ -16,6 +16,7 @@
 #include "api/units/frequency.h"
 #include "api/units/time_delta.h"
 #include "api/units/timestamp.h"
+#include "api/webrtc_key_value_config.h"
 #include "modules/video_coding/rtt_filter.h"
 #include "rtc_base/rolling_accumulator.h"
 
@@ -25,7 +26,8 @@
 
 class VCMJitterEstimator {
  public:
-  explicit VCMJitterEstimator(Clock* clock);
+  explicit VCMJitterEstimator(Clock* clock,
+                              const WebRtcKeyValueConfig& field_trials);
   virtual ~VCMJitterEstimator();
   VCMJitterEstimator(const VCMJitterEstimator&) = delete;
   VCMJitterEstimator& operator=(const VCMJitterEstimator&) = delete;
diff --git a/modules/video_coding/jitter_estimator_tests.cc b/modules/video_coding/jitter_estimator_tests.cc
index f4bb7fc..b1df95b 100644
--- a/modules/video_coding/jitter_estimator_tests.cc
+++ b/modules/video_coding/jitter_estimator_tests.cc
@@ -23,8 +23,8 @@
 #include "rtc_base/strings/string_builder.h"
 #include "rtc_base/time_utils.h"
 #include "system_wrappers/include/clock.h"
-#include "test/field_trial.h"
 #include "test/gtest.h"
+#include "test/scoped_key_value_config.h"
 
 namespace webrtc {
 
@@ -33,10 +33,12 @@
   TestVCMJitterEstimator() : fake_clock_(0) {}
 
   virtual void SetUp() {
-    estimator_ = std::make_unique<VCMJitterEstimator>(&fake_clock_);
+    estimator_ =
+        std::make_unique<VCMJitterEstimator>(&fake_clock_, field_trials_);
   }
 
   SimulatedClock fake_clock_;
+  test::ScopedKeyValueConfig field_trials_;
   std::unique_ptr<VCMJitterEstimator> estimator_;
 };
 
@@ -78,8 +80,8 @@
 }
 
 TEST_F(TestVCMJitterEstimator, TestLowRateDisabled) {
-  test::ScopedFieldTrials field_trials(
-      "WebRTC-ReducedJitterDelayKillSwitch/Enabled/");
+  test::ScopedKeyValueConfig field_trials(
+      field_trials_, "WebRTC-ReducedJitterDelayKillSwitch/Enabled/");
   SetUp();
 
   ValueGenerator gen(10);
@@ -132,7 +134,7 @@
     rtc::SimpleStringBuilder ssb(string_buf);
     ssb << JitterUpperBoundExperiment::kJitterUpperBoundExperimentName
         << "/Enabled-" << context.upper_bound << "/";
-    test::ScopedFieldTrials field_trials(ssb.str());
+    test::ScopedKeyValueConfig field_trials(field_trials_, ssb.str());
     SetUp();
 
     ValueGenerator gen(50);
diff --git a/modules/video_coding/nack_module_unittest.cc b/modules/video_coding/nack_module_unittest.cc
index f91eb75..704f2cd 100644
--- a/modules/video_coding/nack_module_unittest.cc
+++ b/modules/video_coding/nack_module_unittest.cc
@@ -16,8 +16,8 @@
 #include <memory>
 
 #include "system_wrappers/include/clock.h"
-#include "test/field_trial.h"
 #include "test/gtest.h"
+#include "test/scoped_key_value_config.h"
 
 namespace webrtc {
 class TestNackModule : public ::testing::TestWithParam<bool>,
@@ -29,7 +29,7 @@
         field_trial_(GetParam()
                          ? "WebRTC-ExponentialNackBackoff/enabled:true/"
                          : "WebRTC-ExponentialNackBackoff/enabled:false/"),
-        nack_module_(clock_.get(), this, this),
+        nack_module_(clock_.get(), this, this, field_trial_),
         keyframes_requested_(0) {}
 
   void SetUp() override { nack_module_.UpdateRtt(kDefaultRttMs); }
@@ -44,7 +44,7 @@
 
   static constexpr int64_t kDefaultRttMs = 20;
   std::unique_ptr<SimulatedClock> clock_;
-  test::ScopedFieldTrials field_trial_;
+  test::ScopedKeyValueConfig field_trial_;
   DEPRECATED_NackModule nack_module_;
   std::vector<uint16_t> sent_nacks_;
   int keyframes_requested_;
@@ -339,7 +339,7 @@
   TestNackModuleWithFieldTrial()
       : nack_delay_field_trial_("WebRTC-SendNackDelayMs/10/"),
         clock_(new SimulatedClock(0)),
-        nack_module_(clock_.get(), this, this),
+        nack_module_(clock_.get(), this, this, nack_delay_field_trial_),
         keyframes_requested_(0) {}
 
   void SendNack(const std::vector<uint16_t>& sequence_numbers,
@@ -350,7 +350,7 @@
 
   void RequestKeyFrame() override { ++keyframes_requested_; }
 
-  test::ScopedFieldTrials nack_delay_field_trial_;
+  test::ScopedKeyValueConfig nack_delay_field_trial_;
   std::unique_ptr<SimulatedClock> clock_;
   DEPRECATED_NackModule nack_module_;
   std::vector<uint16_t> sent_nacks_;
diff --git a/modules/video_coding/nack_requester.cc b/modules/video_coding/nack_requester.cc
index dac85fc..7cd824e 100644
--- a/modules/video_coding/nack_requester.cc
+++ b/modules/video_coding/nack_requester.cc
@@ -20,7 +20,6 @@
 #include "rtc_base/experiments/field_trial_parser.h"
 #include "rtc_base/logging.h"
 #include "rtc_base/task_queue.h"
-#include "system_wrappers/include/field_trial.h"
 
 namespace webrtc {
 
@@ -33,10 +32,9 @@
 const int kNumReorderingBuckets = 10;
 const int kDefaultSendNackDelayMs = 0;
 
-int64_t GetSendNackDelay() {
+int64_t GetSendNackDelay(const WebRtcKeyValueConfig& field_trials) {
   int64_t delay_ms = strtol(
-      webrtc::field_trial::FindFullName("WebRTC-SendNackDelayMs").c_str(),
-      nullptr, 10);
+      field_trials.Lookup("WebRTC-SendNackDelayMs").c_str(), nullptr, 10);
   if (delay_ms > 0 && delay_ms <= 20) {
     RTC_LOG(LS_INFO) << "SendNackDelay is set to " << delay_ms;
     return delay_ms;
@@ -110,7 +108,8 @@
     : min_retry_interval(min_retry), max_rtt(max_rtt), base(base) {}
 
 absl::optional<NackRequester::BackoffSettings>
-NackRequester::BackoffSettings::ParseFromFieldTrials() {
+NackRequester::BackoffSettings::ParseFromFieldTrials(
+    const WebRtcKeyValueConfig& field_trials) {
   // Matches magic number in RTPSender::OnReceivedNack().
   const TimeDelta kDefaultMinRetryInterval = TimeDelta::Millis(5);
   // Upper bound on link-delay considered for exponential backoff.
@@ -126,7 +125,7 @@
   FieldTrialParameter<TimeDelta> max_rtt("max_rtt", kDefaultMaxRtt);
   FieldTrialParameter<double> base("base", kDefaultBase);
   ParseFieldTrial({&enabled, &min_retry, &max_rtt, &base},
-                  field_trial::FindFullName("WebRTC-ExponentialNackBackoff"));
+                  field_trials.Lookup("WebRTC-ExponentialNackBackoff"));
 
   if (enabled) {
     return NackRequester::BackoffSettings(min_retry.Get(), max_rtt.Get(),
@@ -139,7 +138,8 @@
                              NackPeriodicProcessor* periodic_processor,
                              Clock* clock,
                              NackSender* nack_sender,
-                             KeyFrameRequestSender* keyframe_request_sender)
+                             KeyFrameRequestSender* keyframe_request_sender,
+                             const WebRtcKeyValueConfig& field_trials)
     : worker_thread_(current_queue),
       clock_(clock),
       nack_sender_(nack_sender),
@@ -148,8 +148,8 @@
       initialized_(false),
       rtt_ms_(kDefaultRttMs),
       newest_seq_num_(0),
-      send_nack_delay_ms_(GetSendNackDelay()),
-      backoff_settings_(BackoffSettings::ParseFromFieldTrials()),
+      send_nack_delay_ms_(GetSendNackDelay(field_trials)),
+      backoff_settings_(BackoffSettings::ParseFromFieldTrials(field_trials)),
       processor_registration_(this, periodic_processor) {
   RTC_DCHECK(clock_);
   RTC_DCHECK(nack_sender_);
diff --git a/modules/video_coding/nack_requester.h b/modules/video_coding/nack_requester.h
index 46d904b..a01fb7c 100644
--- a/modules/video_coding/nack_requester.h
+++ b/modules/video_coding/nack_requester.h
@@ -19,6 +19,7 @@
 
 #include "api/sequence_checker.h"
 #include "api/units/time_delta.h"
+#include "api/webrtc_key_value_config.h"
 #include "modules/include/module_common_types.h"
 #include "modules/video_coding/histogram.h"
 #include "rtc_base/numerics/sequence_number_util.h"
@@ -70,7 +71,8 @@
                 NackPeriodicProcessor* periodic_processor,
                 Clock* clock,
                 NackSender* nack_sender,
-                KeyFrameRequestSender* keyframe_request_sender);
+                KeyFrameRequestSender* keyframe_request_sender,
+                const WebRtcKeyValueConfig& field_trials);
   ~NackRequester();
 
   void ProcessNacks() override;
@@ -104,7 +106,8 @@
 
   struct BackoffSettings {
     BackoffSettings(TimeDelta min_retry, TimeDelta max_rtt, double base);
-    static absl::optional<BackoffSettings> ParseFromFieldTrials();
+    static absl::optional<BackoffSettings> ParseFromFieldTrials(
+        const WebRtcKeyValueConfig& field_trials);
 
     // Min time between nacks.
     const TimeDelta min_retry_interval;
diff --git a/modules/video_coding/nack_requester_unittest.cc b/modules/video_coding/nack_requester_unittest.cc
index 0e5d415..2234249 100644
--- a/modules/video_coding/nack_requester_unittest.cc
+++ b/modules/video_coding/nack_requester_unittest.cc
@@ -16,9 +16,9 @@
 #include <memory>
 
 #include "system_wrappers/include/clock.h"
-#include "test/field_trial.h"
 #include "test/gtest.h"
 #include "test/run_loop.h"
+#include "test/scoped_key_value_config.h"
 
 namespace webrtc {
 // TODO(bugs.webrtc.org/11594): Use the use the GlobalSimulatedTimeController
@@ -86,7 +86,7 @@
         std::make_unique<NackPeriodicProcessor>(interval);
     nack_module_ = std::make_unique<NackRequester>(
         TaskQueueBase::Current(), nack_periodic_processor_.get(), clock_.get(),
-        this, this);
+        this, this, field_trial_);
     nack_module_->UpdateRtt(kDefaultRttMs);
     return *nack_module_.get();
   }
@@ -94,7 +94,7 @@
   static constexpr int64_t kDefaultRttMs = 20;
   test::RunLoop loop_;
   std::unique_ptr<SimulatedClock> clock_;
-  test::ScopedFieldTrials field_trial_;
+  test::ScopedKeyValueConfig field_trial_;
   std::unique_ptr<NackPeriodicProcessor> nack_periodic_processor_;
   std::unique_ptr<NackRequester> nack_module_;
   std::vector<uint16_t> sent_nacks_;
@@ -387,7 +387,8 @@
                      &nack_periodic_processor_,
                      clock_.get(),
                      this,
-                     this),
+                     this,
+                     nack_delay_field_trial_),
         keyframes_requested_(0) {}
 
   void SendNack(const std::vector<uint16_t>& sequence_numbers,
@@ -398,7 +399,7 @@
 
   void RequestKeyFrame() override { ++keyframes_requested_; }
 
-  test::ScopedFieldTrials nack_delay_field_trial_;
+  test::ScopedKeyValueConfig nack_delay_field_trial_;
   std::unique_ptr<SimulatedClock> clock_;
   NackPeriodicProcessor nack_periodic_processor_;
   NackRequester nack_module_;
diff --git a/modules/video_coding/receiver.cc b/modules/video_coding/receiver.cc
index e09a056..1503731 100644
--- a/modules/video_coding/receiver.cc
+++ b/modules/video_coding/receiver.cc
@@ -30,18 +30,22 @@
 
 enum { kMaxReceiverDelayMs = 10000 };
 
-VCMReceiver::VCMReceiver(VCMTiming* timing, Clock* clock)
+VCMReceiver::VCMReceiver(VCMTiming* timing,
+                         Clock* clock,
+                         const WebRtcKeyValueConfig& field_trials)
     : VCMReceiver::VCMReceiver(timing,
                                clock,
                                absl::WrapUnique(EventWrapper::Create()),
-                               absl::WrapUnique(EventWrapper::Create())) {}
+                               absl::WrapUnique(EventWrapper::Create()),
+                               field_trials) {}
 
 VCMReceiver::VCMReceiver(VCMTiming* timing,
                          Clock* clock,
                          std::unique_ptr<EventWrapper> receiver_event,
-                         std::unique_ptr<EventWrapper> jitter_buffer_event)
+                         std::unique_ptr<EventWrapper> jitter_buffer_event,
+                         const WebRtcKeyValueConfig& field_trials)
     : clock_(clock),
-      jitter_buffer_(clock_, std::move(jitter_buffer_event)),
+      jitter_buffer_(clock_, std::move(jitter_buffer_event), field_trials),
       timing_(timing),
       render_wait_event_(std::move(receiver_event)),
       max_video_delay_ms_(kMaxVideoDelayMs) {
diff --git a/modules/video_coding/receiver.h b/modules/video_coding/receiver.h
index 8f6b041..c82ec2d 100644
--- a/modules/video_coding/receiver.h
+++ b/modules/video_coding/receiver.h
@@ -14,6 +14,7 @@
 #include <memory>
 #include <vector>
 
+#include "api/webrtc_key_value_config.h"
 #include "modules/video_coding/event_wrapper.h"
 #include "modules/video_coding/include/video_coding.h"
 #include "modules/video_coding/include/video_coding_defines.h"
@@ -28,7 +29,9 @@
 
 class VCMReceiver {
  public:
-  VCMReceiver(VCMTiming* timing, Clock* clock);
+  VCMReceiver(VCMTiming* timing,
+              Clock* clock,
+              const WebRtcKeyValueConfig& field_trials);
 
   // Using this constructor, you can specify a different event implemetation for
   // the jitter buffer. Useful for unit tests when you want to simulate incoming
@@ -37,7 +40,8 @@
   VCMReceiver(VCMTiming* timing,
               Clock* clock,
               std::unique_ptr<EventWrapper> receiver_event,
-              std::unique_ptr<EventWrapper> jitter_buffer_event);
+              std::unique_ptr<EventWrapper> jitter_buffer_event,
+              const WebRtcKeyValueConfig& field_trials);
 
   ~VCMReceiver();
 
diff --git a/modules/video_coding/receiver_unittest.cc b/modules/video_coding/receiver_unittest.cc
index e38f9c5..a9755b7 100644
--- a/modules/video_coding/receiver_unittest.cc
+++ b/modules/video_coding/receiver_unittest.cc
@@ -24,6 +24,7 @@
 #include "rtc_base/checks.h"
 #include "system_wrappers/include/clock.h"
 #include "test/gtest.h"
+#include "test/scoped_key_value_config.h"
 
 namespace webrtc {
 
@@ -31,8 +32,8 @@
  protected:
   TestVCMReceiver()
       : clock_(0),
-        timing_(&clock_),
-        receiver_(&timing_, &clock_),
+        timing_(&clock_, field_trials_),
+        receiver_(&timing_, &clock_, field_trials_),
         stream_generator_(0, clock_.TimeInMilliseconds()) {}
 
   int32_t InsertPacket(int index) {
@@ -78,6 +79,7 @@
     return true;
   }
 
+  test::ScopedKeyValueConfig field_trials_;
   SimulatedClock clock_;
   VCMTiming timing_;
   VCMReceiver receiver_;
@@ -365,16 +367,17 @@
   VCMReceiverTimingTest()
       : clock_(&stream_generator_, &receiver_),
         stream_generator_(0, clock_.TimeInMilliseconds()),
-        timing_(&clock_),
+        timing_(&clock_, field_trials_),
         receiver_(
             &timing_,
             &clock_,
             std::unique_ptr<EventWrapper>(new FrameInjectEvent(&clock_, false)),
-            std::unique_ptr<EventWrapper>(
-                new FrameInjectEvent(&clock_, true))) {}
+            std::unique_ptr<EventWrapper>(new FrameInjectEvent(&clock_, true)),
+            field_trials_) {}
 
   virtual void SetUp() {}
 
+  test::ScopedKeyValueConfig field_trials_;
   SimulatedClockWithFrames clock_;
   StreamGenerator stream_generator_;
   VCMTiming timing_;
diff --git a/modules/video_coding/timing.cc b/modules/video_coding/timing.cc
index 72d1414..da71279 100644
--- a/modules/video_coding/timing.cc
+++ b/modules/video_coding/timing.cc
@@ -16,7 +16,6 @@
 #include "rtc_base/experiments/field_trial_parser.h"
 #include "rtc_base/time/timestamp_extrapolator.h"
 #include "system_wrappers/include/clock.h"
-#include "system_wrappers/include/field_trial.h"
 
 namespace webrtc {
 namespace {
@@ -25,7 +24,7 @@
 constexpr TimeDelta kZeroPlayoutDelayDefaultMinPacing = TimeDelta::Millis(8);
 }  // namespace
 
-VCMTiming::VCMTiming(Clock* clock)
+VCMTiming::VCMTiming(Clock* clock, const WebRtcKeyValueConfig& field_trials)
     : clock_(clock),
       ts_extrapolator_(
           std::make_unique<TimestampExtrapolator>(clock_->CurrentTime())),
@@ -42,9 +41,9 @@
                                      kZeroPlayoutDelayDefaultMinPacing),
       last_decode_scheduled_(Timestamp::Zero()) {
   ParseFieldTrial({&low_latency_renderer_enabled_},
-                  field_trial::FindFullName("WebRTC-LowLatencyRenderer"));
+                  field_trials.Lookup("WebRTC-LowLatencyRenderer"));
   ParseFieldTrial({&zero_playout_delay_min_pacing_},
-                  field_trial::FindFullName("WebRTC-ZeroPlayoutDelay"));
+                  field_trials.Lookup("WebRTC-ZeroPlayoutDelay"));
 }
 
 void VCMTiming::Reset() {
diff --git a/modules/video_coding/timing.h b/modules/video_coding/timing.h
index c1f1c3a..7471740 100644
--- a/modules/video_coding/timing.h
+++ b/modules/video_coding/timing.h
@@ -16,6 +16,7 @@
 #include "absl/types/optional.h"
 #include "api/units/time_delta.h"
 #include "api/video/video_timing.h"
+#include "api/webrtc_key_value_config.h"
 #include "modules/video_coding/codec_timer.h"
 #include "rtc_base/experiments/field_trial_parser.h"
 #include "rtc_base/synchronization/mutex.h"
@@ -32,7 +33,7 @@
   static constexpr auto kDefaultRenderDelay = TimeDelta::Millis(10);
   static constexpr auto kDelayMaxChangeMsPerS = 100;
 
-  explicit VCMTiming(Clock* clock);
+  VCMTiming(Clock* clock, const WebRtcKeyValueConfig& field_trials);
   virtual ~VCMTiming() = default;
 
   // Resets the timing to the initial state.
diff --git a/modules/video_coding/timing_unittest.cc b/modules/video_coding/timing_unittest.cc
index 1f5c12f..20667c9 100644
--- a/modules/video_coding/timing_unittest.cc
+++ b/modules/video_coding/timing_unittest.cc
@@ -13,8 +13,8 @@
 #include "api/units/frequency.h"
 #include "api/units/time_delta.h"
 #include "system_wrappers/include/clock.h"
-#include "test/field_trial.h"
 #include "test/gtest.h"
+#include "test/scoped_key_value_config.h"
 
 namespace webrtc {
 namespace {
@@ -25,8 +25,9 @@
 }  // namespace
 
 TEST(ReceiverTimingTest, JitterDelay) {
+  test::ScopedKeyValueConfig field_trials;
   SimulatedClock clock(0);
-  VCMTiming timing(&clock);
+  VCMTiming timing(&clock, field_trials);
   timing.Reset();
 
   uint32_t timestamp = 0;
@@ -118,8 +119,9 @@
 
 TEST(ReceiverTimingTest, TimestampWrapAround) {
   constexpr auto kStartTime = Timestamp::Millis(1337);
+  test::ScopedKeyValueConfig field_trials;
   SimulatedClock clock(kStartTime);
-  VCMTiming timing(&clock);
+  VCMTiming timing(&clock, field_trials);
 
   // Provoke a wrap-around. The fifth frame will have wrapped at 25 fps.
   constexpr uint32_t kRtpTicksPerFrame = k90kHz / k25Fps;
@@ -143,7 +145,8 @@
   constexpr TimeDelta kTimeDelta = 1 / Frequency::Hertz(60);
   constexpr Timestamp kZeroRenderTime = Timestamp::Zero();
   SimulatedClock clock(kStartTimeUs);
-  VCMTiming timing(&clock);
+  test::ScopedKeyValueConfig field_trials;
+  VCMTiming timing(&clock, field_trials);
   timing.Reset();
   timing.set_max_playout_delay(TimeDelta::Zero());
   for (int i = 0; i < 10; ++i) {
@@ -175,13 +178,13 @@
   // The minimum pacing is enabled by a field trial and active if the RTP
   // playout delay header extension is set to min==0.
   constexpr TimeDelta kMinPacing = TimeDelta::Millis(3);
-  test::ScopedFieldTrials override_field_trials(
+  test::ScopedKeyValueConfig field_trials(
       "WebRTC-ZeroPlayoutDelay/min_pacing:3ms/");
   constexpr int64_t kStartTimeUs = 3.15e13;  // About one year in us.
   constexpr TimeDelta kTimeDelta = 1 / Frequency::Hertz(60);
   constexpr auto kZeroRenderTime = Timestamp::Zero();
   SimulatedClock clock(kStartTimeUs);
-  VCMTiming timing(&clock);
+  VCMTiming timing(&clock, field_trials);
   timing.Reset();
   // MaxWaitingTime() returns zero for evenly spaced video frames.
   for (int i = 0; i < 10; ++i) {
@@ -224,12 +227,12 @@
 TEST(ReceiverTimingTest, DefaultMaxWaitingTimeUnaffectedByPacingExperiment) {
   // The minimum pacing is enabled by a field trial but should not have any
   // effect if render_time_ms is greater than 0;
-  test::ScopedFieldTrials override_field_trials(
+  test::ScopedKeyValueConfig field_trials(
       "WebRTC-ZeroPlayoutDelay/min_pacing:3ms/");
   constexpr int64_t kStartTimeUs = 3.15e13;  // About one year in us.
   const TimeDelta kTimeDelta = TimeDelta::Millis(1000.0 / 60.0);
   SimulatedClock clock(kStartTimeUs);
-  VCMTiming timing(&clock);
+  VCMTiming timing(&clock, field_trials);
   timing.Reset();
   clock.AdvanceTime(kTimeDelta);
   auto now = clock.CurrentTime();
@@ -255,13 +258,13 @@
   // The minimum pacing is enabled by a field trial and active if the RTP
   // playout delay header extension is set to min==0.
   constexpr TimeDelta kMinPacing = TimeDelta::Millis(3);
-  test::ScopedFieldTrials override_field_trials(
+  test::ScopedKeyValueConfig field_trials(
       "WebRTC-ZeroPlayoutDelay/min_pacing:3ms/");
   constexpr int64_t kStartTimeUs = 3.15e13;  // About one year in us.
   const TimeDelta kTimeDelta = TimeDelta::Millis(1000.0 / 60.0);
   constexpr auto kZeroRenderTime = Timestamp::Zero();
   SimulatedClock clock(kStartTimeUs);
-  VCMTiming timing(&clock);
+  VCMTiming timing(&clock, field_trials);
   timing.Reset();
   // MaxWaitingTime() returns zero for evenly spaced video frames.
   for (int i = 0; i < 10; ++i) {
diff --git a/modules/video_coding/video_coding_impl.cc b/modules/video_coding/video_coding_impl.cc
index 0129aa1..f3187d9 100644
--- a/modules/video_coding/video_coding_impl.cc
+++ b/modules/video_coding/video_coding_impl.cc
@@ -14,9 +14,12 @@
 #include <memory>
 
 #include "api/sequence_checker.h"
+#include "api/transport/field_trial_based_config.h"
 #include "api/video/encoded_image.h"
+#include "api/webrtc_key_value_config.h"
 #include "modules/video_coding/include/video_codec_interface.h"
 #include "modules/video_coding/timing.h"
+#include "rtc_base/memory/always_valid_pointer.h"
 #include "system_wrappers/include/clock.h"
 
 namespace webrtc {
@@ -41,10 +44,12 @@
 
 class VideoCodingModuleImpl : public VideoCodingModule {
  public:
-  explicit VideoCodingModuleImpl(Clock* clock)
+  explicit VideoCodingModuleImpl(Clock* clock,
+                                 const WebRtcKeyValueConfig* field_trials)
       : VideoCodingModule(),
-        timing_(new VCMTiming(clock)),
-        receiver_(clock, timing_.get()) {}
+        field_trials_(field_trials),
+        timing_(new VCMTiming(clock, *field_trials_)),
+        receiver_(clock, timing_.get(), *field_trials_) {}
 
   ~VideoCodingModuleImpl() override {}
 
@@ -104,6 +109,8 @@
   }
 
  private:
+  AlwaysValidPointer<const WebRtcKeyValueConfig, FieldTrialBasedConfig>
+      field_trials_;
   SequenceChecker construction_thread_;
   const std::unique_ptr<VCMTiming> timing_;
   vcm::VideoReceiver receiver_;
@@ -112,9 +119,11 @@
 
 // DEPRECATED.  Create method for current interface, will be removed when the
 // new jitter buffer is in place.
-VideoCodingModule* VideoCodingModule::Create(Clock* clock) {
+VideoCodingModule* VideoCodingModule::Create(
+    Clock* clock,
+    const WebRtcKeyValueConfig* field_trials) {
   RTC_DCHECK(clock);
-  return new VideoCodingModuleImpl(clock);
+  return new VideoCodingModuleImpl(clock, field_trials);
 }
 
 }  // namespace webrtc
diff --git a/modules/video_coding/video_coding_impl.h b/modules/video_coding/video_coding_impl.h
index 10ebd41..10adf55 100644
--- a/modules/video_coding/video_coding_impl.h
+++ b/modules/video_coding/video_coding_impl.h
@@ -17,6 +17,7 @@
 
 #include "absl/types/optional.h"
 #include "api/sequence_checker.h"
+#include "api/webrtc_key_value_config.h"
 #include "modules/video_coding/decoder_database.h"
 #include "modules/video_coding/frame_buffer.h"
 #include "modules/video_coding/generic_decoder.h"
@@ -56,7 +57,9 @@
 
 class VideoReceiver : public Module {
  public:
-  VideoReceiver(Clock* clock, VCMTiming* timing);
+  VideoReceiver(Clock* clock,
+                VCMTiming* timing,
+                const WebRtcKeyValueConfig& field_trials);
   ~VideoReceiver() override;
 
   void RegisterReceiveCodec(uint8_t payload_type,
diff --git a/modules/video_coding/video_receiver.cc b/modules/video_coding/video_receiver.cc
index 055d524..ebfdd1b 100644
--- a/modules/video_coding/video_receiver.cc
+++ b/modules/video_coding/video_receiver.cc
@@ -40,11 +40,13 @@
 namespace webrtc {
 namespace vcm {
 
-VideoReceiver::VideoReceiver(Clock* clock, VCMTiming* timing)
+VideoReceiver::VideoReceiver(Clock* clock,
+                             VCMTiming* timing,
+                             const WebRtcKeyValueConfig& field_trials)
     : clock_(clock),
       _timing(timing),
-      _receiver(_timing, clock_),
-      _decodedFrameCallback(_timing, clock_),
+      _receiver(_timing, clock_, field_trials),
+      _decodedFrameCallback(_timing, clock_, field_trials),
       _frameTypeCallback(nullptr),
       _packetRequestCallback(nullptr),
       _scheduleKeyRequest(false),
diff --git a/modules/video_coding/video_receiver2.cc b/modules/video_coding/video_receiver2.cc
index ef6dcf9..e0df761 100644
--- a/modules/video_coding/video_receiver2.cc
+++ b/modules/video_coding/video_receiver2.cc
@@ -28,10 +28,12 @@
 
 namespace webrtc {
 
-VideoReceiver2::VideoReceiver2(Clock* clock, VCMTiming* timing)
+VideoReceiver2::VideoReceiver2(Clock* clock,
+                               VCMTiming* timing,
+                               const WebRtcKeyValueConfig& field_trials)
     : clock_(clock),
       timing_(timing),
-      decodedFrameCallback_(timing_, clock_),
+      decodedFrameCallback_(timing_, clock_, field_trials),
       codecDataBase_() {
   decoder_sequence_checker_.Detach();
 }
diff --git a/modules/video_coding/video_receiver2.h b/modules/video_coding/video_receiver2.h
index 5e087d3..45d774b 100644
--- a/modules/video_coding/video_receiver2.h
+++ b/modules/video_coding/video_receiver2.h
@@ -13,6 +13,7 @@
 
 #include "api/sequence_checker.h"
 #include "api/video_codecs/video_decoder.h"
+#include "api/webrtc_key_value_config.h"
 #include "modules/video_coding/decoder_database.h"
 #include "modules/video_coding/encoded_frame.h"
 #include "modules/video_coding/generic_decoder.h"
@@ -28,7 +29,9 @@
 // VideoCodingModule api.
 class VideoReceiver2 {
  public:
-  VideoReceiver2(Clock* clock, VCMTiming* timing);
+  VideoReceiver2(Clock* clock,
+                 VCMTiming* timing,
+                 const WebRtcKeyValueConfig& field_trials);
   ~VideoReceiver2();
 
   void RegisterReceiveCodec(uint8_t payload_type,
diff --git a/modules/video_coding/video_receiver_unittest.cc b/modules/video_coding/video_receiver_unittest.cc
index fc83141..148ec0d 100644
--- a/modules/video_coding/video_receiver_unittest.cc
+++ b/modules/video_coding/video_receiver_unittest.cc
@@ -15,6 +15,7 @@
 #include "modules/video_coding/video_coding_impl.h"
 #include "system_wrappers/include/clock.h"
 #include "test/gtest.h"
+#include "test/scoped_key_value_config.h"
 
 using ::testing::_;
 using ::testing::AnyNumber;
@@ -51,7 +52,9 @@
   static const uint16_t kMaxWaitTimeMs = 100;
 
   TestVideoReceiver()
-      : clock_(0), timing_(&clock_), receiver_(&clock_, &timing_) {}
+      : clock_(0),
+        timing_(&clock_, field_trials_),
+        receiver_(&clock_, &timing_, field_trials_) {}
 
   virtual void SetUp() {
     // Register decoder.
@@ -118,6 +121,7 @@
     EXPECT_EQ(0, receiver_.Decode(kMaxWaitTimeMs));
   }
 
+  test::ScopedKeyValueConfig field_trials_;
   SimulatedClock clock_;
   NiceMock<MockVideoDecoder> decoder_;
   NiceMock<MockPacketRequestCallback> packet_request_callback_;