Move creating encoder to VideoStreamEncoder.

This used to be in WebRtcVideoChannel::WebRtcVideoSendStream.
One implication is that encoder is not created until the first
frame arrives, and some of the tests needed updates to emit a
frame or two.

Bug: webrtc:8830
Change-Id: I78169b2bb4dfa4197b4b4229af9fd69d0f747835
Reviewed-on: https://webrtc-review.googlesource.com/64885
Commit-Queue: Niels Moller <nisse@webrtc.org>
Reviewed-by: Erik Språng <sprang@webrtc.org>
Reviewed-by: Karl Wiberg <kwiberg@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#22905}
diff --git a/call/bitrate_estimator_tests.cc b/call/bitrate_estimator_tests.cc
index b4f808f..ea48a97 100644
--- a/call/bitrate_estimator_tests.cc
+++ b/call/bitrate_estimator_tests.cc
@@ -116,8 +116,8 @@
 
       video_send_config_ = VideoSendStream::Config(send_transport_.get());
       video_send_config_.rtp.ssrcs.push_back(kVideoSendSsrcs[0]);
-      // Encoders will be set separately per stream.
-      video_send_config_.encoder_settings.encoder = nullptr;
+      video_send_config_.encoder_settings.encoder_factory =
+          &fake_encoder_factory_;
       video_send_config_.rtp.payload_name = "FAKE";
       video_send_config_.rtp.payload_type = kFakeVideoSendPayloadType;
       test::FillEncoderConfiguration(kVideoCodecVP8, 1, &video_encoder_config_);
@@ -162,10 +162,8 @@
           is_sending_receiving_(false),
           send_stream_(nullptr),
           frame_generator_capturer_(),
-          fake_encoder_(Clock::GetRealTimeClock()),
           fake_decoder_() {
       test_->video_send_config_.rtp.ssrcs[0]++;
-      test_->video_send_config_.encoder_settings.encoder = &fake_encoder_;
       send_stream_ = test_->sender_call_->CreateVideoSendStream(
           test_->video_send_config_.Copy(),
           test_->video_encoder_config_.Copy());
@@ -223,7 +221,6 @@
     VideoSendStream* send_stream_;
     VideoReceiveStream* video_receive_stream_;
     std::unique_ptr<test::FrameGeneratorCapturer> frame_generator_capturer_;
-    test::FakeEncoder fake_encoder_;
     test::FakeDecoder fake_decoder_;
   };
 
diff --git a/call/call_perf_tests.cc b/call/call_perf_tests.cc
index 703e5eb..486195f 100644
--- a/call/call_perf_tests.cc
+++ b/call/call_perf_tests.cc
@@ -29,6 +29,7 @@
 #include "test/call_test.h"
 #include "test/direct_transport.h"
 #include "test/drifting_clock.h"
+#include "test/encoder_proxy_factory.h"
 #include "test/encoder_settings.h"
 #include "test/fake_encoder.h"
 #include "test/field_trial.h"
@@ -637,7 +638,7 @@
     std::vector<double> bitrate_kbps_list_;
   } test(pad_to_min_bitrate);
 
-  fake_encoder_.SetMaxBitrate(kMaxEncodeBitrateKbps);
+  fake_encoder_max_bitrate_ = kMaxEncodeBitrateKbps;
   RunBaseTest(&test);
 }
 
@@ -687,7 +688,8 @@
           encoder_inits_(0),
           last_set_bitrate_kbps_(0),
           send_stream_(nullptr),
-          frame_generator_(nullptr) {}
+          frame_generator_(nullptr),
+          encoder_factory_(this) {}
 
     int32_t InitEncode(const VideoCodec* config,
                        int32_t number_of_cores,
@@ -738,7 +740,7 @@
         VideoSendStream::Config* send_config,
         std::vector<VideoReceiveStream::Config>* receive_configs,
         VideoEncoderConfig* encoder_config) override {
-      send_config->encoder_settings.encoder = this;
+      send_config->encoder_settings.encoder_factory = &encoder_factory_;
       encoder_config->max_bitrate_bps = 2 * kReconfigureThresholdKbps * 1000;
       encoder_config->video_stream_factory =
           new rtc::RefCountedObject<VideoStreamFactory>();
@@ -773,6 +775,7 @@
     uint32_t last_set_bitrate_kbps_;
     VideoSendStream* send_stream_;
     test::FrameGeneratorCapturer* frame_generator_;
+    test::EncoderProxyFactory encoder_factory_;
     VideoEncoderConfig encoder_config_;
   } test;
 
diff --git a/call/video_send_stream.cc b/call/video_send_stream.cc
index 8fccd32..ec701d0 100644
--- a/call/video_send_stream.cc
+++ b/call/video_send_stream.cc
@@ -93,7 +93,6 @@
   rtc::SimpleStringBuilder ss(buf);
   ss << "{encoder_factory: "
      << (encoder_factory ? "(VideoEncoderFactory)" : "(nullptr)");
-  ss << ", encoder: " << (encoder ? "(VideoEncoder)" : "nullptr");
   ss << '}';
   return ss.str();
 }
diff --git a/call/video_send_stream.h b/call/video_send_stream.h
index 0019a95..cdb9483 100644
--- a/call/video_send_stream.h
+++ b/call/video_send_stream.h
@@ -113,18 +113,8 @@
 
     struct EncoderSettings {
       EncoderSettings() = default;
-      explicit EncoderSettings(VideoEncoder* encoder) : encoder(encoder) {}
       std::string ToString() const;
 
-      // TODO(sophiechang): Delete this field when no one is using internal
-      // sources anymore.
-      bool internal_source = false;
-
-      // Allow 100% encoder utilization. Used for HW encoders where CPU isn't
-      // expected to be the limiting factor, but a chip could be running at
-      // 30fps (for example) exactly.
-      bool full_overuse_time = false;
-
       // Enables the new method to estimate the cpu load from encoding, used for
       // cpu adaptation.
       bool experiment_cpu_load_estimator = false;
@@ -132,9 +122,8 @@
       // Ownership stays with WebrtcVideoEngine (delegated from PeerConnection).
       VideoEncoderFactory* encoder_factory = nullptr;
 
-      // TODO(nisse): Delete, let VideoStreamEncoder create the encoder.
-      // Uninitialized VideoEncoder instance to be used for encoding. Will be
-      // initialized from inside the VideoSendStream.
+      // TODO(nisse): Unused! But kept temporarily to transition downstream
+      // projects.
       VideoEncoder* encoder = nullptr;
     } encoder_settings;
 
diff --git a/media/engine/fakewebrtccall.cc b/media/engine/fakewebrtccall.cc
index 0aa9cb0..728193e 100644
--- a/media/engine/fakewebrtccall.cc
+++ b/media/engine/fakewebrtccall.cc
@@ -123,7 +123,7 @@
       framerate_scaling_enabled_(false),
       source_(nullptr),
       num_swapped_frames_(0) {
-  RTC_DCHECK(config.encoder_settings.encoder != NULL);
+  RTC_DCHECK(config.encoder_settings.encoder_factory != nullptr);
   ReconfigureVideoEncoder(std::move(encoder_config));
 }
 
diff --git a/media/engine/webrtcvideoengine.cc b/media/engine/webrtcvideoengine.cc
index 7f6508b..e9ceaaa 100644
--- a/media/engine/webrtcvideoengine.cc
+++ b/media/engine/webrtcvideoengine.cc
@@ -1656,8 +1656,6 @@
   if (stream_ != NULL) {
     call_->DestroyVideoSendStream(stream_);
   }
-  // Release |allocated_encoder_|.
-  allocated_encoder_.reset();
 }
 
 bool WebRtcVideoChannel::WebRtcVideoSendStream::SetVideoSend(
@@ -1729,26 +1727,6 @@
   parameters_.encoder_config = CreateVideoEncoderConfig(codec_settings.codec);
   RTC_DCHECK_GT(parameters_.encoder_config.number_of_streams, 0);
 
-  const webrtc::SdpVideoFormat format(codec_settings.codec.name,
-                                      codec_settings.codec.params);
-
-  // We can't overwrite |allocated_encoder_| immediately, because we
-  // need to release it after the RecreateWebRtcStream() call.
-  std::unique_ptr<webrtc::VideoEncoder> new_encoder =
-      // TODO(nisse): Leave to VideoStreamEncoder.
-      parameters_.config.encoder_settings.encoder_factory->CreateVideoEncoder(
-          format);
-
-  parameters_.config.encoder_settings.encoder = new_encoder.get();
-
-  const webrtc::VideoEncoderFactory::CodecInfo info =
-      parameters_.config.encoder_settings.encoder_factory->QueryVideoEncoder(
-          format);
-  parameters_.config.encoder_settings.full_overuse_time =
-      info.is_hardware_accelerated;
-  parameters_.config.encoder_settings.internal_source =
-      info.has_internal_source;
-
   parameters_.config.rtp.payload_name = codec_settings.codec.name;
   parameters_.config.rtp.payload_type = codec_settings.codec.id;
   parameters_.config.rtp.ulpfec = codec_settings.ulpfec;
@@ -1772,9 +1750,10 @@
 
   parameters_.codec_settings = codec_settings;
 
+  // TODO(nisse): Avoid recreation, it should be enough to call
+  // ReconfigureEncoder.
   RTC_LOG(LS_INFO) << "RecreateWebRtcStream (send) because of SetCodec.";
   RecreateWebRtcStream();
-  allocated_encoder_ = std::move(new_encoder);
 }
 
 void WebRtcVideoChannel::WebRtcVideoSendStream::SetSendParameters(
@@ -1907,6 +1886,8 @@
   RTC_DCHECK_RUN_ON(&thread_checker_);
   webrtc::VideoEncoderConfig encoder_config;
   encoder_config.codec_type = webrtc::PayloadStringToCodecType(codec.name);
+  encoder_config.video_format =
+      webrtc::SdpVideoFormat(codec.name, codec.params);
 
   bool is_screencast = parameters_.options.is_screencast.value_or(false);
   if (is_screencast) {
diff --git a/media/engine/webrtcvideoengine.h b/media/engine/webrtcvideoengine.h
index bffe344..e17da3d 100644
--- a/media/engine/webrtcvideoengine.h
+++ b/media/engine/webrtcvideoengine.h
@@ -350,8 +350,6 @@
     // TODO(skvlad): Combine parameters_ and rtp_parameters_ once we have only
     // one stream per MediaChannel.
     webrtc::RtpParameters rtp_parameters_ RTC_GUARDED_BY(&thread_checker_);
-    std::unique_ptr<webrtc::VideoEncoder> allocated_encoder_
-        RTC_GUARDED_BY(&thread_checker_);
 
     bool sending_ RTC_GUARDED_BY(&thread_checker_);
   };
diff --git a/media/engine/webrtcvideoengine_unittest.cc b/media/engine/webrtcvideoengine_unittest.cc
index cbc3446..86ba066 100644
--- a/media/engine/webrtcvideoengine_unittest.cc
+++ b/media/engine/webrtcvideoengine_unittest.cc
@@ -496,40 +496,6 @@
       codecs, FindMatchingCodec(codecs, h264_high)->id));
 }
 
-void WebRtcVideoEngineTest::TestExtendedEncoderOveruse(
-    bool use_external_encoder) {
-  std::unique_ptr<VideoMediaChannel> channel;
-  FakeCall* fake_call = new FakeCall();
-  call_.reset(fake_call);
-  if (use_external_encoder) {
-    encoder_factory_->AddSupportedVideoCodecType("VP8");
-    channel.reset(SetUpForExternalEncoderFactory());
-  } else {
-    channel.reset(
-        engine_.CreateChannel(call_.get(), GetMediaConfig(), VideoOptions()));
-  }
-  ASSERT_TRUE(
-      channel->AddSendStream(cricket::StreamParams::CreateLegacy(kSsrc)));
-  cricket::VideoSendParameters parameters;
-  parameters.codecs.push_back(GetEngineCodec("VP8"));
-  EXPECT_TRUE(channel->SetSendParameters(parameters));
-  EXPECT_TRUE(channel->SetSend(true));
-  FakeVideoSendStream* stream = fake_call->GetVideoSendStreams()[0];
-
-  EXPECT_EQ(use_external_encoder,
-            stream->GetConfig().encoder_settings.full_overuse_time);
-  // Remove stream previously added to free the external encoder instance.
-  EXPECT_TRUE(channel->RemoveSendStream(kSsrc));
-}
-
-TEST_F(WebRtcVideoEngineTest, EnablesFullEncoderTimeForExternalEncoders) {
-  TestExtendedEncoderOveruse(true);
-}
-
-TEST_F(WebRtcVideoEngineTest, DisablesFullEncoderTimeForNonExternalEncoders) {
-  TestExtendedEncoderOveruse(false);
-}
-
 #if !defined(RTC_DISABLE_VP9)
 TEST_F(WebRtcVideoEngineTest, CanConstructDecoderForVp9EncoderFactory) {
   encoder_factory_->AddSupportedVideoCodecType("VP9");
@@ -688,16 +654,29 @@
 TEST_F(WebRtcVideoEngineTest, ChannelWithExternalH264CanChangeToInternalVp8) {
   encoder_factory_->AddSupportedVideoCodecType("H264");
 
+  // Set capturer.
+  FakeVideoCapturerWithTaskQueue capturer;
+  EXPECT_EQ(cricket::CS_RUNNING,
+            capturer.Start(capturer.GetSupportedFormats()->front()));
+
   std::unique_ptr<VideoMediaChannel> channel(SetUpForExternalEncoderFactory());
 
   EXPECT_TRUE(
       channel->AddSendStream(cricket::StreamParams::CreateLegacy(kSsrc)));
-  ASSERT_EQ(1u, encoder_factory_->encoders().size());
+  EXPECT_TRUE(channel->SetVideoSend(kSsrc, nullptr, &capturer));
+  // Sending one frame will have allocate the encoder.
+  EXPECT_TRUE(capturer.CaptureFrame());
+
+  ASSERT_EQ_WAIT(1u, encoder_factory_->encoders().size(), kTimeout);
 
   cricket::VideoSendParameters parameters;
   parameters.codecs.push_back(GetEngineCodec("VP8"));
   EXPECT_TRUE(channel->SetSendParameters(parameters));
-  ASSERT_EQ(0u, encoder_factory_->encoders().size());
+
+  // Sending one frame will switch encoder.
+  EXPECT_TRUE(capturer.CaptureFrame());
+
+  EXPECT_EQ_WAIT(0u, encoder_factory_->encoders().size(), kTimeout);
 }
 
 TEST_F(WebRtcVideoEngineTest,
@@ -765,7 +744,6 @@
 
   EXPECT_TRUE(
       channel->AddSendStream(cricket::StreamParams::CreateLegacy(kSsrc)));
-  ASSERT_EQ(1u, encoder_factory_->encoders().size());
 
   // Send a frame of 720p. This should trigger a "real" encoder initialization.
   cricket::VideoFormat format(
@@ -774,6 +752,8 @@
   EXPECT_TRUE(channel->SetVideoSend(kSsrc, nullptr, &capturer));
   EXPECT_EQ(cricket::CS_RUNNING, capturer.Start(format));
   EXPECT_TRUE(capturer.CaptureFrame());
+  ASSERT_TRUE(encoder_factory_->WaitForCreatedVideoEncoders(1));
+  ASSERT_EQ(1u, encoder_factory_->encoders().size());
   ASSERT_TRUE(encoder_factory_->encoders()[0]->WaitForInitEncode());
   EXPECT_EQ(webrtc::kVideoCodecH264,
             encoder_factory_->encoders()[0]->GetCodecSettings().codecType);
@@ -800,6 +780,7 @@
   EXPECT_EQ(cricket::CS_RUNNING, capturer.Start(format));
   EXPECT_TRUE(capturer.CaptureFrame());
 
+  ASSERT_TRUE(encoder_factory_->WaitForCreatedVideoEncoders(1));
   ASSERT_EQ(1u, encoder_factory_->encoders().size());
   FakeWebRtcVideoEncoder* encoder = encoder_factory_->encoders()[0];
   ASSERT_TRUE(encoder_factory_->encoders()[0]->WaitForInitEncode());
@@ -988,8 +969,12 @@
   EXPECT_CALL(*encoder_factory, QueryVideoEncoder(format))
       .WillRepeatedly(testing::Return(codec_info));
   FakeWebRtcVideoEncoder* const encoder = new FakeWebRtcVideoEncoder();
+  rtc::Event encoder_created(false, false);
   EXPECT_CALL(*encoder_factory, CreateVideoEncoderProxy(format))
-      .WillOnce(testing::Return(encoder));
+      .WillOnce(
+          ::testing::DoAll(::testing::InvokeWithoutArgs(
+                               [&encoder_created]() { encoder_created.Set(); }),
+                           ::testing::Return(encoder)));
 
   // Mock decoder creation. |engine| take ownership of the decoder.
   FakeWebRtcVideoDecoder* const decoder = new FakeWebRtcVideoDecoder();
@@ -1013,6 +998,15 @@
       send_channel->AddSendStream(StreamParams::CreateLegacy(send_ssrc)));
   EXPECT_TRUE(send_channel->SetSend(true));
 
+  // Set capturer.
+  FakeVideoCapturerWithTaskQueue capturer;
+  EXPECT_EQ(cricket::CS_RUNNING,
+            capturer.Start(capturer.GetSupportedFormats()->front()));
+  EXPECT_TRUE(send_channel->SetVideoSend(send_ssrc, nullptr, &capturer));
+  // Sending one frame will allocate the encoder.
+  EXPECT_TRUE(capturer.CaptureFrame());
+  encoder_created.Wait(kTimeout);
+
   // Create recv channel.
   const int recv_ssrc = 321;
   std::unique_ptr<VideoMediaChannel> recv_channel(
diff --git a/test/BUILD.gn b/test/BUILD.gn
index 7a26e63..ece4003 100644
--- a/test/BUILD.gn
+++ b/test/BUILD.gn
@@ -509,6 +509,7 @@
     "constants.h",
     "drifting_clock.cc",
     "drifting_clock.h",
+    "encoder_proxy_factory.h",
     "encoder_settings.cc",
     "encoder_settings.h",
     "fake_decoder.cc",
@@ -516,6 +517,7 @@
     "fake_encoder.cc",
     "fake_encoder.h",
     "fake_videorenderer.h",
+    "function_video_encoder_factory.h",
     "layer_filtering_transport.cc",
     "layer_filtering_transport.h",
     "mock_transport.cc",
diff --git a/test/call_test.cc b/test/call_test.cc
index 4e62865..e3a73e8 100644
--- a/test/call_test.cc
+++ b/test/call_test.cc
@@ -20,6 +20,7 @@
 #include "rtc_base/checks.h"
 #include "rtc_base/event.h"
 #include "rtc_base/ptr_util.h"
+#include "test/fake_encoder.h"
 #include "test/testsupport/fileutils.h"
 
 namespace webrtc {
@@ -37,7 +38,11 @@
       video_send_stream_(nullptr),
       audio_send_config_(nullptr),
       audio_send_stream_(nullptr),
-      fake_encoder_(clock_),
+      fake_encoder_factory_([this]() {
+        auto encoder = rtc::MakeUnique<test::FakeEncoder>(clock_);
+        encoder->SetMaxBitrate(fake_encoder_max_bitrate_);
+        return encoder;
+      }),
       num_video_streams_(1),
       num_audio_streams_(0),
       num_flexfec_streams_(0),
@@ -193,7 +198,7 @@
                                      Transport* send_transport) {
   RTC_DCHECK_LE(num_video_streams + num_used_ssrcs, kNumSsrcs);
   *video_config = VideoSendStream::Config(send_transport);
-  video_config->encoder_settings.encoder = &fake_encoder_;
+  video_config->encoder_settings.encoder_factory = &fake_encoder_factory_;
   video_config->rtp.payload_name = "FAKE";
   video_config->rtp.payload_type = kFakeVideoSendPayloadType;
   video_config->rtp.extensions.push_back(
diff --git a/test/call_test.h b/test/call_test.h
index c096b0d..4191f43 100644
--- a/test/call_test.h
+++ b/test/call_test.h
@@ -19,9 +19,9 @@
 #include "modules/audio_device/include/test_audio_device.h"
 #include "test/encoder_settings.h"
 #include "test/fake_decoder.h"
-#include "test/fake_encoder.h"
 #include "test/fake_videorenderer.h"
 #include "test/frame_generator_capturer.h"
+#include "test/function_video_encoder_factory.h"
 #include "test/rtp_rtcp_observer.h"
 #include "test/single_threaded_task_queue.h"
 
@@ -138,7 +138,8 @@
   std::vector<FlexfecReceiveStream*> flexfec_receive_streams_;
 
   std::unique_ptr<test::FrameGeneratorCapturer> frame_generator_capturer_;
-  test::FakeEncoder fake_encoder_;
+  test::FunctionVideoEncoderFactory fake_encoder_factory_;
+  int fake_encoder_max_bitrate_ = -1;
   std::vector<std::unique_ptr<VideoDecoder>> allocated_decoders_;
   size_t num_video_streams_;
   size_t num_audio_streams_;
diff --git a/test/encoder_proxy_factory.h b/test/encoder_proxy_factory.h
new file mode 100644
index 0000000..9c7ff0c
--- /dev/null
+++ b/test/encoder_proxy_factory.h
@@ -0,0 +1,103 @@
+/*
+ *  Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef TEST_ENCODER_PROXY_FACTORY_H_
+#define TEST_ENCODER_PROXY_FACTORY_H_
+
+#include <memory>
+#include <vector>
+
+#include "api/video_codecs/video_encoder.h"
+#include "api/video_codecs/video_encoder_factory.h"
+#include "rtc_base/ptr_util.h"
+
+namespace webrtc {
+namespace test {
+
+// An encoder factory with a single underlying VideoEncoder object,
+// intended for test purposes. Each call to CreateVideoEncoder returns
+// a proxy for the same encoder, typically an instance of FakeEncoder.
+class EncoderProxyFactory final : public VideoEncoderFactory {
+ public:
+  explicit EncoderProxyFactory(VideoEncoder* encoder) : encoder_(encoder) {
+    codec_info_.is_hardware_accelerated = false;
+    codec_info_.has_internal_source = false;
+  }
+
+  // Unused by tests.
+  std::vector<SdpVideoFormat> GetSupportedFormats() const override {
+    RTC_NOTREACHED();
+    return {};
+  }
+
+  CodecInfo QueryVideoEncoder(const SdpVideoFormat& format) const override {
+    return codec_info_;
+  }
+
+  std::unique_ptr<VideoEncoder> CreateVideoEncoder(
+      const SdpVideoFormat& format) override {
+    return rtc::MakeUnique<EncoderProxy>(encoder_);
+  }
+
+  void SetIsHardwareAccelerated(bool is_hardware_accelerated) {
+    codec_info_.is_hardware_accelerated = is_hardware_accelerated;
+  }
+  void SetHasInternalSource(bool has_internal_source) {
+    codec_info_.has_internal_source = has_internal_source;
+  }
+
+ private:
+  // Wrapper class, since CreateVideoEncoder needs to surrender
+  // ownership to the object it returns.
+  class EncoderProxy final : public VideoEncoder {
+   public:
+    explicit EncoderProxy(VideoEncoder* encoder) : encoder_(encoder) {}
+
+   private:
+    int32_t Encode(const VideoFrame& input_image,
+                   const CodecSpecificInfo* codec_specific_info,
+                   const std::vector<FrameType>* frame_types) override {
+      return encoder_->Encode(input_image, codec_specific_info, frame_types);
+    }
+    int32_t InitEncode(const VideoCodec* config,
+                       int32_t number_of_cores,
+                       size_t max_payload_size) override {
+      return encoder_->InitEncode(config, number_of_cores, max_payload_size);
+    }
+    VideoEncoder::ScalingSettings GetScalingSettings() const override {
+      return encoder_->GetScalingSettings();
+    }
+    int32_t RegisterEncodeCompleteCallback(
+        EncodedImageCallback* callback) override {
+      return encoder_->RegisterEncodeCompleteCallback(callback);
+    }
+    int32_t Release() override { return encoder_->Release(); }
+    int32_t SetChannelParameters(uint32_t packet_loss, int64_t rtt) override {
+      return encoder_->SetChannelParameters(packet_loss, rtt);
+    }
+    int32_t SetRateAllocation(const BitrateAllocation& rate_allocation,
+                              uint32_t framerate) override {
+      return encoder_->SetRateAllocation(rate_allocation, framerate);
+    }
+    const char* ImplementationName() const override {
+      return encoder_->ImplementationName();
+    }
+
+    VideoEncoder* const encoder_;
+  };
+
+  VideoEncoder* const encoder_;
+  CodecInfo codec_info_;
+};
+
+}  // namespace test
+}  // namespace webrtc
+
+#endif  // TEST_ENCODER_PROXY_FACTORY_H_
diff --git a/test/function_video_encoder_factory.h b/test/function_video_encoder_factory.h
new file mode 100644
index 0000000..22cf744
--- /dev/null
+++ b/test/function_video_encoder_factory.h
@@ -0,0 +1,59 @@
+/*
+ *  Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef TEST_FUNCTION_VIDEO_ENCODER_FACTORY_H_
+#define TEST_FUNCTION_VIDEO_ENCODER_FACTORY_H_
+
+#include <functional>
+#include <memory>
+#include <utility>
+#include <vector>
+
+#include "api/video_codecs/video_encoder_factory.h"
+
+namespace webrtc {
+namespace test {
+
+// An encoder factory producing encoders by calling a supplied create
+// function.
+class FunctionVideoEncoderFactory final : public VideoEncoderFactory {
+ public:
+  explicit FunctionVideoEncoderFactory(
+      std::function<std::unique_ptr<VideoEncoder>()> create)
+      : create_(std::move(create)) {
+    codec_info_.is_hardware_accelerated = false;
+    codec_info_.has_internal_source = false;
+  }
+
+  // Unused by tests.
+  std::vector<SdpVideoFormat> GetSupportedFormats() const override {
+    RTC_NOTREACHED();
+    return {};
+  }
+
+  CodecInfo QueryVideoEncoder(
+      const SdpVideoFormat& /* format */) const override {
+    return codec_info_;
+  }
+
+  std::unique_ptr<VideoEncoder> CreateVideoEncoder(
+      const SdpVideoFormat& /* format */) override {
+    return create_();
+  }
+
+ private:
+  const std::function<std::unique_ptr<VideoEncoder>()> create_;
+  CodecInfo codec_info_;
+};
+
+}  // namespace test
+}  // namespace webrtc
+
+#endif  // TEST_FUNCTION_VIDEO_ENCODER_FACTORY_H_
diff --git a/video/encoder_rtcp_feedback_unittest.cc b/video/encoder_rtcp_feedback_unittest.cc
index fbe590b..ec5a1ce 100644
--- a/video/encoder_rtcp_feedback_unittest.cc
+++ b/video/encoder_rtcp_feedback_unittest.cc
@@ -24,12 +24,11 @@
 class MockVideoStreamEncoder : public VideoStreamEncoder {
  public:
   explicit MockVideoStreamEncoder(SendStatisticsProxy* send_stats_proxy)
-      : VideoStreamEncoder(
-            1,
-            send_stats_proxy,
-            VideoSendStream::Config::EncoderSettings(nullptr),
-            nullptr,
-            rtc::MakeUnique<OveruseFrameDetector>(nullptr)) {}
+      : VideoStreamEncoder(1,
+                           send_stats_proxy,
+                           VideoSendStream::Config::EncoderSettings(),
+                           nullptr,
+                           rtc::MakeUnique<OveruseFrameDetector>(nullptr)) {}
   ~MockVideoStreamEncoder() { Stop(); }
 
   MOCK_METHOD0(SendKeyFrame, void());
diff --git a/video/end_to_end_tests/bandwidth_tests.cc b/video/end_to_end_tests/bandwidth_tests.cc
index e77f402..50e874b 100644
--- a/video/end_to_end_tests/bandwidth_tests.cc
+++ b/video/end_to_end_tests/bandwidth_tests.cc
@@ -12,6 +12,8 @@
 #include "rtc_base/rate_limiter.h"
 #include "system_wrappers/include/sleep.h"
 #include "test/call_test.h"
+#include "test/encoder_proxy_factory.h"
+#include "test/fake_encoder.h"
 #include "test/field_trial.h"
 #include "test/gtest.h"
 #include "test/rtcp_packet_parser.h"
@@ -280,6 +282,7 @@
           FakeEncoder(Clock::GetRealTimeClock()),
           task_queue_(task_queue),
           send_stream_(nullptr),
+          encoder_factory_(this),
           bitrate_kbps_(0) {}
 
     void OnVideoStreamsCreated(
@@ -292,7 +295,7 @@
         VideoSendStream::Config* send_config,
         std::vector<VideoReceiveStream::Config>* receive_configs,
         VideoEncoderConfig* encoder_config) override {
-      send_config->encoder_settings.encoder = this;
+      send_config->encoder_settings.encoder_factory = &encoder_factory_;
       RTC_DCHECK_EQ(1, encoder_config->number_of_streams);
     }
 
@@ -350,6 +353,7 @@
     test::SingleThreadedTaskQueueForTesting* const task_queue_;
     rtc::CriticalSection crit_;
     VideoSendStream* send_stream_;
+    test::EncoderProxyFactory encoder_factory_;
     uint32_t bitrate_kbps_ RTC_GUARDED_BY(crit_);
   } test(&task_queue_);
 
diff --git a/video/end_to_end_tests/codec_tests.cc b/video/end_to_end_tests/codec_tests.cc
index 1607382..71034cc 100644
--- a/video/end_to_end_tests/codec_tests.cc
+++ b/video/end_to_end_tests/codec_tests.cc
@@ -18,6 +18,7 @@
 #include "test/call_test.h"
 #include "test/encoder_settings.h"
 #include "test/field_trial.h"
+#include "test/function_video_encoder_factory.h"
 #include "test/gtest.h"
 
 namespace webrtc {
@@ -47,7 +48,7 @@
   CodecObserver(int no_frames_to_wait_for,
                 VideoRotation rotation_to_test,
                 const std::string& payload_name,
-                std::unique_ptr<webrtc::VideoEncoder> encoder,
+                VideoEncoderFactory* encoder_factory,
                 std::unique_ptr<webrtc::VideoDecoder> decoder)
       : EndToEndTest(4 * CodecEndToEndTest::kDefaultTimeoutMs),
         // TODO(hta): This timeout (120 seconds) is excessive.
@@ -55,7 +56,7 @@
         no_frames_to_wait_for_(no_frames_to_wait_for),
         expected_rotation_(rotation_to_test),
         payload_name_(payload_name),
-        encoder_(std::move(encoder)),
+        encoder_factory_(encoder_factory),
         decoder_(std::move(decoder)),
         frame_counter_(0) {}
 
@@ -69,7 +70,7 @@
       std::vector<VideoReceiveStream::Config>* receive_configs,
       VideoEncoderConfig* encoder_config) override {
     encoder_config->codec_type = PayloadStringToCodecType(payload_name_);
-    send_config->encoder_settings.encoder = encoder_.get();
+    send_config->encoder_settings.encoder_factory = encoder_factory_;
     send_config->rtp.payload_name = payload_name_;
     send_config->rtp.payload_type = test::CallTest::kVideoSendPayloadType;
 
@@ -97,56 +98,70 @@
   int no_frames_to_wait_for_;
   VideoRotation expected_rotation_;
   std::string payload_name_;
-  std::unique_ptr<webrtc::VideoEncoder> encoder_;
+  VideoEncoderFactory* encoder_factory_;
   std::unique_ptr<webrtc::VideoDecoder> decoder_;
   int frame_counter_;
 };
 
 TEST_P(CodecEndToEndTest, SendsAndReceivesVP8) {
-  CodecObserver test(5, kVideoRotation_0, "VP8", VP8Encoder::Create(),
+  test::FunctionVideoEncoderFactory encoder_factory(
+      []() { return VP8Encoder::Create(); });
+  CodecObserver test(5, kVideoRotation_0, "VP8", &encoder_factory,
                      VP8Decoder::Create());
   RunBaseTest(&test);
 }
 
 TEST_P(CodecEndToEndTest, SendsAndReceivesVP8Rotation90) {
-  CodecObserver test(5, kVideoRotation_90, "VP8", VP8Encoder::Create(),
+  test::FunctionVideoEncoderFactory encoder_factory(
+      []() { return VP8Encoder::Create(); });
+  CodecObserver test(5, kVideoRotation_90, "VP8", &encoder_factory,
                      VP8Decoder::Create());
   RunBaseTest(&test);
 }
 
 #if !defined(RTC_DISABLE_VP9)
 TEST_P(CodecEndToEndTest, SendsAndReceivesVP9) {
-  CodecObserver test(500, kVideoRotation_0, "VP9", VP9Encoder::Create(),
+  test::FunctionVideoEncoderFactory encoder_factory(
+      []() { return VP9Encoder::Create(); });
+  CodecObserver test(500, kVideoRotation_0, "VP9", &encoder_factory,
                      VP9Decoder::Create());
   RunBaseTest(&test);
 }
 
 TEST_P(CodecEndToEndTest, SendsAndReceivesVP9VideoRotation90) {
-  CodecObserver test(5, kVideoRotation_90, "VP9", VP9Encoder::Create(),
+  test::FunctionVideoEncoderFactory encoder_factory(
+      []() { return VP9Encoder::Create(); });
+  CodecObserver test(5, kVideoRotation_90, "VP9", &encoder_factory,
                      VP9Decoder::Create());
   RunBaseTest(&test);
 }
 
 // Mutiplex tests are using VP9 as the underlying implementation.
 TEST_P(CodecEndToEndTest, SendsAndReceivesMultiplex) {
-  InternalEncoderFactory encoder_factory;
+  InternalEncoderFactory internal_encoder_factory;
   InternalDecoderFactory decoder_factory;
+  test::FunctionVideoEncoderFactory encoder_factory(
+      [&internal_encoder_factory]() {
+        return rtc::MakeUnique<MultiplexEncoderAdapter>(
+            &internal_encoder_factory, SdpVideoFormat(cricket::kVp9CodecName));
+      });
   CodecObserver test(
-      5, kVideoRotation_0, "multiplex",
-      rtc::MakeUnique<MultiplexEncoderAdapter>(
-          &encoder_factory, SdpVideoFormat(cricket::kVp9CodecName)),
+      5, kVideoRotation_0, "multiplex", &encoder_factory,
       rtc::MakeUnique<MultiplexDecoderAdapter>(
           &decoder_factory, SdpVideoFormat(cricket::kVp9CodecName)));
   RunBaseTest(&test);
 }
 
 TEST_P(CodecEndToEndTest, SendsAndReceivesMultiplexVideoRotation90) {
-  InternalEncoderFactory encoder_factory;
+  InternalEncoderFactory internal_encoder_factory;
   InternalDecoderFactory decoder_factory;
+  test::FunctionVideoEncoderFactory encoder_factory(
+      [&internal_encoder_factory]() {
+        return rtc::MakeUnique<MultiplexEncoderAdapter>(
+            &internal_encoder_factory, SdpVideoFormat(cricket::kVp9CodecName));
+      });
   CodecObserver test(
-      5, kVideoRotation_90, "multiplex",
-      rtc::MakeUnique<MultiplexEncoderAdapter>(
-          &encoder_factory, SdpVideoFormat(cricket::kVp9CodecName)),
+      5, kVideoRotation_90, "multiplex", &encoder_factory,
       rtc::MakeUnique<MultiplexDecoderAdapter>(
           &decoder_factory, SdpVideoFormat(cricket::kVp9CodecName)));
   RunBaseTest(&test);
@@ -167,15 +182,17 @@
                         h264_field_trial_combinations);
 
 TEST_P(EndToEndTestH264, SendsAndReceivesH264) {
-  CodecObserver test(500, kVideoRotation_0, "H264",
-                     H264Encoder::Create(cricket::VideoCodec("H264")),
+  test::FunctionVideoEncoderFactory encoder_factory(
+      []() { return H264Encoder::Create(cricket::VideoCodec("H264")); });
+  CodecObserver test(500, kVideoRotation_0, "H264", &encoder_factory,
                      H264Decoder::Create());
   RunBaseTest(&test);
 }
 
 TEST_P(EndToEndTestH264, SendsAndReceivesH264VideoRotation90) {
-  CodecObserver test(5, kVideoRotation_90, "H264",
-                     H264Encoder::Create(cricket::VideoCodec("H264")),
+  test::FunctionVideoEncoderFactory encoder_factory(
+      []() { return H264Encoder::Create(cricket::VideoCodec("H264")); });
+  CodecObserver test(5, kVideoRotation_90, "H264", &encoder_factory,
                      H264Decoder::Create());
   RunBaseTest(&test);
 }
@@ -183,7 +200,9 @@
 TEST_P(EndToEndTestH264, SendsAndReceivesH264PacketizationMode0) {
   cricket::VideoCodec codec = cricket::VideoCodec("H264");
   codec.SetParam(cricket::kH264FmtpPacketizationMode, "0");
-  CodecObserver test(500, kVideoRotation_0, "H264", H264Encoder::Create(codec),
+  test::FunctionVideoEncoderFactory encoder_factory(
+      [codec]() { return H264Encoder::Create(codec); });
+  CodecObserver test(500, kVideoRotation_0, "H264", &encoder_factory,
                      H264Decoder::Create());
   RunBaseTest(&test);
 }
@@ -191,7 +210,9 @@
 TEST_P(EndToEndTestH264, SendsAndReceivesH264PacketizationMode1) {
   cricket::VideoCodec codec = cricket::VideoCodec("H264");
   codec.SetParam(cricket::kH264FmtpPacketizationMode, "1");
-  CodecObserver test(500, kVideoRotation_0, "H264", H264Encoder::Create(codec),
+  test::FunctionVideoEncoderFactory encoder_factory(
+      [codec]() { return H264Encoder::Create(codec); });
+  CodecObserver test(500, kVideoRotation_0, "H264", &encoder_factory,
                      H264Decoder::Create());
   RunBaseTest(&test);
 }
diff --git a/video/end_to_end_tests/fec_tests.cc b/video/end_to_end_tests/fec_tests.cc
index 80a97cd..67bfdeb 100644
--- a/video/end_to_end_tests/fec_tests.cc
+++ b/video/end_to_end_tests/fec_tests.cc
@@ -12,6 +12,7 @@
 #include "modules/video_coding/codecs/vp8/include/vp8.h"
 #include "test/call_test.h"
 #include "test/field_trial.h"
+#include "test/function_video_encoder_factory.h"
 #include "test/gtest.h"
 #include "test/rtcp_packet_parser.h"
 
@@ -42,7 +43,7 @@
    public:
     UlpfecRenderObserver()
         : EndToEndTest(kDefaultTimeoutMs),
-          encoder_(VP8Encoder::Create()),
+          encoder_factory_([]() { return VP8Encoder::Create(); }),
           random_(0xcafef00d1),
           num_packets_sent_(0) {}
 
@@ -102,7 +103,7 @@
         VideoEncoderConfig* encoder_config) override {
       // Use VP8 instead of FAKE, since the latter does not have PictureID
       // in the packetization headers.
-      send_config->encoder_settings.encoder = encoder_.get();
+      send_config->encoder_settings.encoder_factory = &encoder_factory_;
       send_config->rtp.payload_name = "VP8";
       send_config->rtp.payload_type = kVideoSendPayloadType;
       encoder_config->codec_type = kVideoCodecVP8;
@@ -128,6 +129,7 @@
 
     rtc::CriticalSection crit_;
     std::unique_ptr<VideoEncoder> encoder_;
+    test::FunctionVideoEncoderFactory encoder_factory_;
     std::unique_ptr<VideoDecoder> decoder_;
     std::set<uint32_t> dropped_sequence_numbers_ RTC_GUARDED_BY(crit_);
     // Several packets can have the same timestamp.
@@ -335,7 +337,7 @@
           ulpfec_sequence_number_(0),
           has_last_sequence_number_(false),
           last_sequence_number_(0),
-          encoder_(VP8Encoder::Create()),
+          encoder_factory_([]() { return VP8Encoder::Create(); }),
           decoder_(VP8Decoder::Create()) {}
 
    private:
@@ -452,7 +454,7 @@
       send_config->rtp.ulpfec.red_payload_type = kRedPayloadType;
       send_config->rtp.ulpfec.ulpfec_payload_type = kUlpfecPayloadType;
       // Set codec to VP8, otherwise NACK/FEC hybrid will be disabled.
-      send_config->encoder_settings.encoder = encoder_.get();
+      send_config->encoder_settings.encoder_factory = &encoder_factory_;
       send_config->rtp.payload_name = "VP8";
       send_config->rtp.payload_type = kFakeVideoSendPayloadType;
       encoder_config->codec_type = kVideoCodecVP8;
@@ -488,6 +490,7 @@
     bool has_last_sequence_number_;
     uint16_t last_sequence_number_;
     std::unique_ptr<webrtc::VideoEncoder> encoder_;
+    test::FunctionVideoEncoderFactory encoder_factory_;
     std::unique_ptr<webrtc::VideoDecoder> decoder_;
   } test;
 
diff --git a/video/end_to_end_tests/histogram_tests.cc b/video/end_to_end_tests/histogram_tests.cc
index decbb77..3096c2a 100644
--- a/video/end_to_end_tests/histogram_tests.cc
+++ b/video/end_to_end_tests/histogram_tests.cc
@@ -12,6 +12,7 @@
 #include "system_wrappers/include/metrics.h"
 #include "system_wrappers/include/metrics_default.h"
 #include "test/call_test.h"
+#include "test/function_video_encoder_factory.h"
 #include "test/gtest.h"
 #include "test/rtcp_packet_parser.h"
 
@@ -34,7 +35,7 @@
           use_fec_(use_fec),
           screenshare_(screenshare),
           // This test uses NACK, so to send FEC we can't use a fake encoder.
-          vp8_encoder_(use_fec ? VP8Encoder::Create() : nullptr),
+          encoder_factory_([]() { return VP8Encoder::Create(); }),
           sender_call_(nullptr),
           receiver_call_(nullptr),
           start_runtime_ms_(-1),
@@ -88,7 +89,7 @@
       if (use_fec_) {
         send_config->rtp.ulpfec.ulpfec_payload_type = kUlpfecPayloadType;
         send_config->rtp.ulpfec.red_payload_type = kRedPayloadType;
-        send_config->encoder_settings.encoder = vp8_encoder_.get();
+        send_config->encoder_settings.encoder_factory = &encoder_factory_;
         send_config->rtp.payload_name = "VP8";
         encoder_config->codec_type = kVideoCodecVP8;
         (*receive_configs)[0].decoders[0].payload_name = "VP8";
@@ -130,7 +131,7 @@
     const bool use_rtx_;
     const bool use_fec_;
     const bool screenshare_;
-    const std::unique_ptr<VideoEncoder> vp8_encoder_;
+    test::FunctionVideoEncoderFactory encoder_factory_;
     Call* sender_call_;
     Call* receiver_call_;
     int64_t start_runtime_ms_;
diff --git a/video/end_to_end_tests/log_tests.cc b/video/end_to_end_tests/log_tests.cc
index 2695667..391c3d0 100644
--- a/video/end_to_end_tests/log_tests.cc
+++ b/video/end_to_end_tests/log_tests.cc
@@ -11,6 +11,7 @@
 #include "modules/video_coding/codecs/vp8/include/vp8.h"
 #include "rtc_base/file.h"
 #include "test/call_test.h"
+#include "test/function_video_encoder_factory.h"
 #include "test/testsupport/fileutils.h"
 
 namespace webrtc {
@@ -61,6 +62,7 @@
     explicit LogEncodingObserver(LogEndToEndTest* fixture)
         : EndToEndTest(kDefaultTimeoutMs),
           fixture_(fixture),
+          encoder_factory_([]() { return VP8Encoder::Create(); }),
           recorded_frames_(0) {}
 
     void PerformTest() override {
@@ -73,12 +75,11 @@
         VideoSendStream::Config* send_config,
         std::vector<VideoReceiveStream::Config>* receive_configs,
         VideoEncoderConfig* encoder_config) override {
-      encoder_ = VP8Encoder::Create();
       decoder_ = VP8Decoder::Create();
 
       send_config->post_encode_callback = this;
       send_config->rtp.payload_name = "VP8";
-      send_config->encoder_settings.encoder = encoder_.get();
+      send_config->encoder_settings.encoder_factory = &encoder_factory_;
       encoder_config->codec_type = kVideoCodecVP8;
 
       (*receive_configs)[0].decoders.resize(1);
@@ -107,7 +108,7 @@
 
    private:
     LogEndToEndTest* const fixture_;
-    std::unique_ptr<VideoEncoder> encoder_;
+    test::FunctionVideoEncoderFactory encoder_factory_;
     std::unique_ptr<VideoDecoder> decoder_;
     rtc::CriticalSection crit_;
     int recorded_frames_ RTC_GUARDED_BY(crit_);
diff --git a/video/end_to_end_tests/multi_stream_tester.cc b/video/end_to_end_tests/multi_stream_tester.cc
index 2d501c1..e818cf4 100644
--- a/video/end_to_end_tests/multi_stream_tester.cc
+++ b/video/end_to_end_tests/multi_stream_tester.cc
@@ -18,6 +18,7 @@
 #include "modules/video_coding/codecs/vp8/include/vp8.h"
 #include "test/call_test.h"
 #include "test/encoder_settings.h"
+#include "test/function_video_encoder_factory.h"
 
 namespace webrtc {
 
@@ -48,7 +49,8 @@
   VideoReceiveStream* receive_streams[kNumStreams];
   test::FrameGeneratorCapturer* frame_generators[kNumStreams];
   std::vector<std::unique_ptr<VideoDecoder>> allocated_decoders;
-  std::unique_ptr<VideoEncoder> encoders[kNumStreams];
+  test::FunctionVideoEncoderFactory encoder_factory(
+      []() { return VP8Encoder::Create(); });
 
   task_queue_->SendTask([&]() {
     sender_call = rtc::WrapUnique(Call::Create(config));
@@ -61,9 +63,6 @@
     sender_transport->SetReceiver(receiver_call->Receiver());
     receiver_transport->SetReceiver(sender_call->Receiver());
 
-    for (size_t i = 0; i < kNumStreams; ++i)
-      encoders[i] = VP8Encoder::Create();
-
     for (size_t i = 0; i < kNumStreams; ++i) {
       uint32_t ssrc = codec_settings[i].ssrc;
       int width = codec_settings[i].width;
@@ -71,7 +70,7 @@
 
       VideoSendStream::Config send_config(sender_transport.get());
       send_config.rtp.ssrcs.push_back(ssrc);
-      send_config.encoder_settings.encoder = encoders[i].get();
+      send_config.encoder_settings.encoder_factory = &encoder_factory;
       send_config.rtp.payload_name = "VP8";
       send_config.rtp.payload_type = kVideoPayloadType;
       VideoEncoderConfig encoder_config;
diff --git a/video/end_to_end_tests/network_state_tests.cc b/video/end_to_end_tests/network_state_tests.cc
index 1222363..9af0c47 100644
--- a/video/end_to_end_tests/network_state_tests.cc
+++ b/video/end_to_end_tests/network_state_tests.cc
@@ -10,6 +10,8 @@
 
 #include "system_wrappers/include/sleep.h"
 #include "test/call_test.h"
+#include "test/encoder_proxy_factory.h"
+#include "test/fake_encoder.h"
 #include "test/gtest.h"
 
 namespace webrtc {
@@ -77,12 +79,15 @@
     MediaType network_to_bring_up,
     VideoEncoder* encoder,
     Transport* transport) {
-  task_queue_.SendTask([this, network_to_bring_up, encoder, transport]() {
+  test::EncoderProxyFactory encoder_factory(encoder);
+
+  task_queue_.SendTask([this, network_to_bring_up, &encoder_factory,
+                        transport]() {
     CreateSenderCall(Call::Config(event_log_.get()));
     sender_call_->SignalChannelNetworkState(network_to_bring_up, kNetworkUp);
 
     CreateSendConfig(1, 0, 0, transport);
-    video_send_config_.encoder_settings.encoder = encoder;
+    video_send_config_.encoder_settings.encoder_factory = &encoder_factory;
     CreateVideoStreams();
     CreateFrameGeneratorCapturer(kDefaultFramerate, kDefaultWidth,
                                  kDefaultHeight);
@@ -151,6 +156,7 @@
           packet_event_(false, false),
           sender_call_(nullptr),
           receiver_call_(nullptr),
+          encoder_factory_(this),
           sender_state_(kNetworkUp),
           sender_rtp_(0),
           sender_padding_(0),
@@ -197,7 +203,7 @@
         VideoSendStream::Config* send_config,
         std::vector<VideoReceiveStream::Config>* receive_configs,
         VideoEncoderConfig* encoder_config) override {
-      send_config->encoder_settings.encoder = this;
+      send_config->encoder_settings.encoder_factory = &encoder_factory_;
     }
 
     void PerformTest() override {
@@ -329,6 +335,7 @@
     rtc::Event packet_event_;
     Call* sender_call_;
     Call* receiver_call_;
+    test::EncoderProxyFactory encoder_factory_;
     NetworkState sender_state_ RTC_GUARDED_BY(test_crit_);
     int sender_rtp_ RTC_GUARDED_BY(test_crit_);
     int sender_padding_ RTC_GUARDED_BY(test_crit_);
diff --git a/video/end_to_end_tests/retransmission_tests.cc b/video/end_to_end_tests/retransmission_tests.cc
index aefb02c..425c0c2 100644
--- a/video/end_to_end_tests/retransmission_tests.cc
+++ b/video/end_to_end_tests/retransmission_tests.cc
@@ -12,6 +12,7 @@
 #include "system_wrappers/include/sleep.h"
 #include "test/call_test.h"
 #include "test/field_trial.h"
+#include "test/function_video_encoder_factory.h"
 #include "test/gtest.h"
 #include "test/rtcp_packet_parser.h"
 
@@ -339,7 +340,7 @@
           retransmission_ssrc_(enable_rtx ? kSendRtxSsrcs[0]
                                           : kVideoSendSsrcs[0]),
           retransmission_payload_type_(GetPayloadType(enable_rtx, enable_red)),
-          encoder_(VP8Encoder::Create()),
+          encoder_factory_([]() { return VP8Encoder::Create(); }),
           marker_bits_observed_(0),
           retransmitted_timestamp_(0) {}
 
@@ -437,7 +438,7 @@
       // Configure encoding and decoding with VP8, since generic packetization
       // doesn't support FEC with NACK.
       RTC_DCHECK_EQ(1, (*receive_configs)[0].decoders.size());
-      send_config->encoder_settings.encoder = encoder_.get();
+      send_config->encoder_settings.encoder_factory = &encoder_factory_;
       send_config->rtp.payload_name = "VP8";
       encoder_config->codec_type = kVideoCodecVP8;
       (*receive_configs)[0].decoders[0].payload_name = "VP8";
@@ -469,7 +470,7 @@
     const int payload_type_;
     const uint32_t retransmission_ssrc_;
     const int retransmission_payload_type_;
-    std::unique_ptr<VideoEncoder> encoder_;
+    test::FunctionVideoEncoderFactory encoder_factory_;
     const std::string payload_name_;
     int marker_bits_observed_;
     uint32_t retransmitted_timestamp_ RTC_GUARDED_BY(&crit_);
diff --git a/video/end_to_end_tests/rtp_rtcp_tests.cc b/video/end_to_end_tests/rtp_rtcp_tests.cc
index c12b988..5317242 100644
--- a/video/end_to_end_tests/rtp_rtcp_tests.cc
+++ b/video/end_to_end_tests/rtp_rtcp_tests.cc
@@ -468,7 +468,8 @@
 
   std::unique_ptr<test::PacketTransport> send_transport;
   std::unique_ptr<test::PacketTransport> receive_transport;
-  std::unique_ptr<VideoEncoder> encoder;
+  test::FunctionVideoEncoderFactory encoder_factory(
+      []() { return VP8Encoder::Create(); });
 
   task_queue_.SendTask([&]() {
     CreateCalls(config, config);
@@ -494,8 +495,8 @@
     const int kNumFlexfecStreams = 1;
     CreateSendConfig(kNumVideoStreams, 0, kNumFlexfecStreams,
                      send_transport.get());
-    encoder = VP8Encoder::Create();
-    video_send_config_.encoder_settings.encoder = encoder.get();
+
+    video_send_config_.encoder_settings.encoder_factory = &encoder_factory;
     video_send_config_.rtp.payload_name = "VP8";
     video_send_config_.rtp.payload_type = kVideoSendPayloadType;
     video_send_config_.rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
diff --git a/video/end_to_end_tests/stats_tests.cc b/video/end_to_end_tests/stats_tests.cc
index 643b6c1..f3d2194 100644
--- a/video/end_to_end_tests/stats_tests.cc
+++ b/video/end_to_end_tests/stats_tests.cc
@@ -14,6 +14,8 @@
 #include "system_wrappers/include/metrics_default.h"
 #include "system_wrappers/include/sleep.h"
 #include "test/call_test.h"
+#include "test/fake_encoder.h"
+#include "test/function_video_encoder_factory.h"
 #include "test/gtest.h"
 #include "test/rtcp_packet_parser.h"
 
@@ -37,7 +39,10 @@
    public:
     StatsObserver()
         : EndToEndTest(kLongTimeoutMs),
-          encoder_(Clock::GetRealTimeClock(), 10),
+          encoder_factory_([]() {
+            return rtc::MakeUnique<test::DelayedEncoder>(
+                Clock::GetRealTimeClock(), 10);
+          }),
           send_stream_(nullptr),
           expected_send_ssrcs_(),
           check_stats_event_(false, false) {}
@@ -297,7 +302,7 @@
 
       // Use a delayed encoder to make sure we see CpuOveruseMetrics stats that
       // are non-zero.
-      send_config->encoder_settings.encoder = &encoder_;
+      send_config->encoder_settings.encoder_factory = &encoder_factory_;
     }
 
     size_t GetNumVideoStreams() const override { return kNumSimulcastStreams; }
@@ -349,7 +354,7 @@
       }
     }
 
-    test::DelayedEncoder encoder_;
+    test::FunctionVideoEncoderFactory encoder_factory_;
     std::vector<VideoReceiveStream*> receive_streams_;
     std::map<std::string, bool> receive_stats_filled_;
 
diff --git a/video/overuse_frame_detector.cc b/video/overuse_frame_detector.cc
index 1d6b0e1..4bccdf3 100644
--- a/video/overuse_frame_detector.cc
+++ b/video/overuse_frame_detector.cc
@@ -543,8 +543,10 @@
 }
 void OveruseFrameDetector::StopCheckForOveruse() {
   RTC_DCHECK_CALLED_SEQUENTIALLY(&task_checker_);
-  check_overuse_task_->Stop();
-  check_overuse_task_ = nullptr;
+  if (check_overuse_task_) {
+    check_overuse_task_->Stop();
+    check_overuse_task_ = nullptr;
+  }
 }
 
 void OveruseFrameDetector::EncodedFrameTimeMeasured(int encode_duration_ms) {
diff --git a/video/overuse_frame_detector.h b/video/overuse_frame_detector.h
index 3aa0db1..3525a97 100644
--- a/video/overuse_frame_detector.h
+++ b/video/overuse_frame_detector.h
@@ -118,6 +118,8 @@
   void CheckForOveruse(AdaptationObserverInterface* overuse_observer);
   void SetOptions(const CpuOveruseOptions& options);
 
+  CpuOveruseOptions options_;
+
  private:
   class CheckOveruseTask;
 
@@ -137,8 +139,6 @@
   // Owned by the task queue from where StartCheckForOveruse is called.
   CheckOveruseTask* check_overuse_task_;
 
-  CpuOveruseOptions options_;
-
   // Stats metrics.
   CpuOveruseMetricsObserver* const metrics_observer_;
   rtc::Optional<CpuOveruseMetrics> metrics_ RTC_GUARDED_BY(task_checker_);
diff --git a/video/picture_id_tests.cc b/video/picture_id_tests.cc
index ff62ddc..33aed38 100644
--- a/video/picture_id_tests.cc
+++ b/video/picture_id_tests.cc
@@ -14,6 +14,7 @@
 #include "rtc_base/numerics/safe_conversions.h"
 #include "rtc_base/numerics/sequence_number_util.h"
 #include "test/call_test.h"
+#include "test/function_video_encoder_factory.h"
 
 namespace webrtc {
 namespace {
@@ -235,7 +236,8 @@
     });
   }
 
-  void SetupEncoder(VideoEncoder* encoder, const std::string& payload_name);
+  void SetupEncoder(VideoEncoderFactory* encoder_factory,
+                    const std::string& payload_name);
   void TestPictureIdContinuousAfterReconfigure(
       const std::vector<int>& ssrc_counts);
   void TestPictureIdIncreaseAfterRecreateStreams(
@@ -292,12 +294,12 @@
   const size_t num_of_temporal_layers_;
 };
 
-void PictureIdTest::SetupEncoder(VideoEncoder* encoder,
+void PictureIdTest::SetupEncoder(VideoEncoderFactory* encoder_factory,
                                  const std::string& payload_name) {
   observer_.reset(
       new PictureIdObserver(PayloadNameToRtpVideoCodecType(payload_name)));
 
-  task_queue_.SendTask([this, &encoder, payload_name]() {
+  task_queue_.SendTask([this, encoder_factory, payload_name]() {
     Call::Config config(event_log_.get());
     CreateCalls(config, config);
 
@@ -307,7 +309,7 @@
         FakeNetworkPipe::Config()));
 
     CreateSendConfig(kNumSimulcastStreams, 0, 0, send_transport_.get());
-    video_send_config_.encoder_settings.encoder = encoder;
+    video_send_config_.encoder_settings.encoder_factory = encoder_factory;
     video_send_config_.rtp.payload_name = payload_name;
     video_encoder_config_.codec_type = PayloadStringToCodecType(payload_name);
     video_encoder_config_.video_stream_factory =
@@ -390,51 +392,67 @@
 }
 
 TEST_P(PictureIdTest, ContinuousAfterReconfigureVp8) {
-  std::unique_ptr<VideoEncoder> encoder(VP8Encoder::Create());
-  SetupEncoder(encoder.get(), "VP8");
+  test::FunctionVideoEncoderFactory encoder_factory(
+      []() { return VP8Encoder::Create(); });
+  SetupEncoder(&encoder_factory, "VP8");
   TestPictureIdContinuousAfterReconfigure({1, 3, 3, 1, 1});
 }
 
 TEST_P(PictureIdTest, IncreasingAfterRecreateStreamVp8) {
-  std::unique_ptr<VideoEncoder> encoder(VP8Encoder::Create());
-  SetupEncoder(encoder.get(), "VP8");
+  test::FunctionVideoEncoderFactory encoder_factory(
+      []() { return VP8Encoder::Create(); });
+  SetupEncoder(&encoder_factory, "VP8");
   TestPictureIdIncreaseAfterRecreateStreams({1, 3, 3, 1, 1});
 }
 
 TEST_P(PictureIdTest, ContinuousAfterStreamCountChangeVp8) {
-  std::unique_ptr<VideoEncoder> encoder(VP8Encoder::Create());
+  test::FunctionVideoEncoderFactory encoder_factory(
+      []() { return VP8Encoder::Create(); });
   // Make sure that the picture id is not reset if the stream count goes
   // down and then up.
-  SetupEncoder(encoder.get(), "VP8");
+  SetupEncoder(&encoder_factory, "VP8");
   TestPictureIdContinuousAfterReconfigure({3, 1, 3});
 }
 
 TEST_P(PictureIdTest, ContinuousAfterReconfigureSimulcastEncoderAdapter) {
   InternalEncoderFactory internal_encoder_factory;
-  SimulcastEncoderAdapter simulcast_encoder_adapter(&internal_encoder_factory);
-  SetupEncoder(&simulcast_encoder_adapter, "VP8");
+  test::FunctionVideoEncoderFactory encoder_factory(
+      [&internal_encoder_factory]() {
+        return rtc::MakeUnique<SimulcastEncoderAdapter>(
+            &internal_encoder_factory);
+      });
+  SetupEncoder(&encoder_factory, "VP8");
   TestPictureIdContinuousAfterReconfigure({1, 3, 3, 1, 1});
 }
 
 TEST_P(PictureIdTest, IncreasingAfterRecreateStreamSimulcastEncoderAdapter) {
   InternalEncoderFactory internal_encoder_factory;
-  SimulcastEncoderAdapter simulcast_encoder_adapter(&internal_encoder_factory);
-  SetupEncoder(&simulcast_encoder_adapter, "VP8");
+  test::FunctionVideoEncoderFactory encoder_factory(
+      [&internal_encoder_factory]() {
+        return rtc::MakeUnique<SimulcastEncoderAdapter>(
+            &internal_encoder_factory);
+      });
+  SetupEncoder(&encoder_factory, "VP8");
   TestPictureIdIncreaseAfterRecreateStreams({1, 3, 3, 1, 1});
 }
 
 TEST_P(PictureIdTest, ContinuousAfterStreamCountChangeSimulcastEncoderAdapter) {
   InternalEncoderFactory internal_encoder_factory;
-  SimulcastEncoderAdapter simulcast_encoder_adapter(&internal_encoder_factory);
+  test::FunctionVideoEncoderFactory encoder_factory(
+      [&internal_encoder_factory]() {
+        return rtc::MakeUnique<SimulcastEncoderAdapter>(
+            &internal_encoder_factory);
+      });
   // Make sure that the picture id is not reset if the stream count goes
   // down and then up.
-  SetupEncoder(&simulcast_encoder_adapter, "VP8");
+  SetupEncoder(&encoder_factory, "VP8");
   TestPictureIdContinuousAfterReconfigure({3, 1, 3});
 }
 
 TEST_P(PictureIdTest, IncreasingAfterRecreateStreamVp9) {
-  std::unique_ptr<VideoEncoder> encoder(VP9Encoder::Create());
-  SetupEncoder(encoder.get(), "VP9");
+  test::FunctionVideoEncoderFactory encoder_factory(
+      []() { return VP9Encoder::Create(); });
+  SetupEncoder(&encoder_factory, "VP9");
   TestPictureIdIncreaseAfterRecreateStreams({1, 1});
 }
 
diff --git a/video/video_quality_test.cc b/video/video_quality_test.cc
index 0a477c4..d0edfc7 100644
--- a/video/video_quality_test.cc
+++ b/video/video_quality_test.cc
@@ -26,6 +26,7 @@
 #include "modules/rtp_rtcp/source/rtp_utility.h"
 #include "modules/video_coding/codecs/h264/include/h264.h"
 #include "modules/video_coding/codecs/multiplex/include/multiplex_encoder_adapter.h"
+#include "modules/video_coding/codecs/vp8/include/vp8.h"
 #include "modules/video_coding/codecs/vp8/include/vp8_common_types.h"
 #include "modules/video_coding/codecs/vp9/include/vp9.h"
 #include "rtc_base/cpu_time.h"
@@ -1074,6 +1075,36 @@
   const int64_t start_ms_;
 };
 
+// Not used by these tests.
+std::vector<SdpVideoFormat>
+VideoQualityTest::TestVideoEncoderFactory::GetSupportedFormats() const {
+  RTC_NOTREACHED();
+  return {};
+}
+
+VideoEncoderFactory::CodecInfo
+VideoQualityTest::TestVideoEncoderFactory::QueryVideoEncoder(
+    const SdpVideoFormat& format) const {
+  CodecInfo codec_info;
+  codec_info.is_hardware_accelerated = false;
+  codec_info.has_internal_source = false;
+  return codec_info;
+}
+
+std::unique_ptr<VideoEncoder>
+VideoQualityTest::TestVideoEncoderFactory::CreateVideoEncoder(
+    const SdpVideoFormat& format) {
+  if (format.name == "VP8") {
+    return rtc::MakeUnique<VP8EncoderSimulcastProxy>(
+        &internal_encoder_factory_);
+  } else if (format.name == "multiplex") {
+    return rtc::MakeUnique<MultiplexEncoderAdapter>(
+        &internal_encoder_factory_, SdpVideoFormat(cricket::kVp9CodecName));
+  } else {
+    return internal_encoder_factory_.CreateVideoEncoder(format);
+  }
+}
+
 VideoQualityTest::VideoQualityTest()
     : clock_(Clock::GetRealTimeClock()), receive_logs_(0), send_logs_(0) {
   payload_type_map_ = test::CallTest::payload_type_map_;
@@ -1354,7 +1385,6 @@
   CreateMatchingAudioAndFecConfigs(recv_transport);
   video_receive_configs_.clear();
   video_send_configs_.clear();
-  video_encoders_.clear();
   video_encoder_configs_.clear();
   allocated_decoders_.clear();
   bool decode_all_receive_streams = true;
@@ -1363,7 +1393,6 @@
   video_encoder_configs_.resize(num_video_streams_);
   for (size_t video_idx = 0; video_idx < num_video_streams_; ++video_idx) {
     video_send_configs_.push_back(VideoSendStream::Config(send_transport));
-    video_encoders_.push_back(nullptr);
     video_encoder_configs_.push_back(VideoEncoderConfig());
     num_video_substreams = params_.ss[video_idx].streams.size();
     RTC_CHECK_GT(num_video_substreams, 0);
@@ -1372,26 +1401,20 @@
 
     int payload_type;
     if (params_.video[video_idx].codec == "H264") {
-      video_encoders_[video_idx] =
-          H264Encoder::Create(cricket::VideoCodec("H264"));
       payload_type = kPayloadTypeH264;
     } else if (params_.video[video_idx].codec == "VP8") {
-      video_encoders_[video_idx] =
-          rtc::MakeUnique<VP8EncoderSimulcastProxy>(&internal_encoder_factory_);
       payload_type = kPayloadTypeVP8;
     } else if (params_.video[video_idx].codec == "VP9") {
-      video_encoders_[video_idx] = VP9Encoder::Create();
       payload_type = kPayloadTypeVP9;
     } else if (params_.video[video_idx].codec == "multiplex") {
-      video_encoders_[video_idx] = rtc::MakeUnique<MultiplexEncoderAdapter>(
-          &internal_encoder_factory_, SdpVideoFormat(cricket::kVp9CodecName));
       payload_type = kPayloadTypeVP9;
     } else {
       RTC_NOTREACHED() << "Codec not supported!";
       return;
     }
-    video_send_configs_[video_idx].encoder_settings.encoder =
-        video_encoders_[video_idx].get();
+    video_send_configs_[video_idx].encoder_settings.encoder_factory =
+        &video_encoder_factory_;
+
     video_send_configs_[video_idx].rtp.payload_name =
         params_.video[video_idx].codec;
     video_send_configs_[video_idx].rtp.payload_type = payload_type;
@@ -1416,6 +1439,9 @@
     video_send_configs_[video_idx].rtp.extensions.push_back(RtpExtension(
         RtpExtension::kVideoTimingUri, test::kVideoTimingExtensionId));
 
+    video_encoder_configs_[video_idx].video_format.name =
+        params_.video[video_idx].codec;
+
     video_encoder_configs_[video_idx].codec_type =
         PayloadStringToCodecType(params_.video[video_idx].codec);
 
@@ -1600,14 +1626,13 @@
 void VideoQualityTest::SetupThumbnails(Transport* send_transport,
                                        Transport* recv_transport) {
   for (int i = 0; i < params_.call.num_thumbnails; ++i) {
-    thumbnail_encoders_.emplace_back(VP8Encoder::Create());
-
     // Thumbnails will be send in the other way: from receiver_call to
     // sender_call.
     VideoSendStream::Config thumbnail_send_config(recv_transport);
     thumbnail_send_config.rtp.ssrcs.push_back(kThumbnailSendSsrcStart + i);
-    thumbnail_send_config.encoder_settings.encoder =
-        thumbnail_encoders_.back().get();
+    // TODO(nisse): Could use a simpler VP8-only encoder factory.
+    thumbnail_send_config.encoder_settings.encoder_factory =
+        &video_encoder_factory_;
     thumbnail_send_config.rtp.payload_name = params_.video[0].codec;
     thumbnail_send_config.rtp.payload_type = kPayloadTypeVP8;
     thumbnail_send_config.rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
@@ -1625,6 +1650,7 @@
 
     VideoEncoderConfig thumbnail_encoder_config;
     thumbnail_encoder_config.codec_type = kVideoCodecVP8;
+    thumbnail_encoder_config.video_format.name = "VP8";
     thumbnail_encoder_config.min_transmit_bitrate_bps = 7500;
     thumbnail_send_config.suspend_below_min_bitrate =
         params_.video[0].suspend_below_min_bitrate;
diff --git a/video/video_quality_test.h b/video/video_quality_test.h
index 688a004..749d092 100644
--- a/video/video_quality_test.h
+++ b/video/video_quality_test.h
@@ -112,6 +112,18 @@
       const std::vector<std::string>& sl_descriptors);
 
  protected:
+  class TestVideoEncoderFactory : public VideoEncoderFactory {
+    std::vector<SdpVideoFormat> GetSupportedFormats() const override;
+
+    CodecInfo QueryVideoEncoder(const SdpVideoFormat& format) const override;
+
+    std::unique_ptr<VideoEncoder> CreateVideoEncoder(
+        const SdpVideoFormat& format) override;
+
+   private:
+    InternalEncoderFactory internal_encoder_factory_;
+  };
+
   std::map<uint8_t, webrtc::MediaType> payload_type_map_;
   std::unique_ptr<FecControllerFactoryInterface> fec_controller_factory_;
 
@@ -148,10 +160,8 @@
 
   std::vector<std::unique_ptr<test::VideoCapturer>> video_capturers_;
   std::vector<std::unique_ptr<test::VideoCapturer>> thumbnail_capturers_;
-  InternalEncoderFactory internal_encoder_factory_;
-  std::vector<std::unique_ptr<VideoEncoder>> video_encoders_;
+  TestVideoEncoderFactory video_encoder_factory_;
 
-  std::vector<std::unique_ptr<VideoEncoder>> thumbnail_encoders_;
   std::vector<VideoSendStream::Config> thumbnail_send_configs_;
   std::vector<VideoEncoderConfig> thumbnail_encoder_configs_;
   std::vector<VideoSendStream*> thumbnail_send_streams_;
diff --git a/video/video_send_stream.cc b/video/video_send_stream.cc
index 4152efd..27f8ef5 100644
--- a/video/video_send_stream.cc
+++ b/video/video_send_stream.cc
@@ -512,6 +512,8 @@
                    encoder_config.content_type),
       config_(std::move(config)),
       content_type_(encoder_config.content_type) {
+  RTC_DCHECK(config_.encoder_settings.encoder_factory);
+
   video_stream_encoder_ = rtc::MakeUnique<VideoStreamEncoder>(
       num_cpu_cores, &stats_proxy_,
       config_.encoder_settings,
@@ -826,7 +828,6 @@
     transport_->RegisterPacketFeedbackObserver(this);
   }
 
-  RTC_DCHECK(config_->encoder_settings.encoder);
   RTC_DCHECK_GE(config_->rtp.payload_type, 0);
   RTC_DCHECK_LE(config_->rtp.payload_type, 127);
 
diff --git a/video/video_send_stream_tests.cc b/video/video_send_stream_tests.cc
index 9985b85..deac1e6 100644
--- a/video/video_send_stream_tests.cc
+++ b/video/video_send_stream_tests.cc
@@ -33,6 +33,8 @@
 #include "system_wrappers/include/sleep.h"
 #include "test/call_test.h"
 #include "test/configurable_frame_size_encoder.h"
+#include "test/encoder_proxy_factory.h"
+#include "test/fake_encoder.h"
 #include "test/fake_texture_frame.h"
 #include "test/field_trial.h"
 #include "test/frame_generator.h"
@@ -198,8 +200,10 @@
   class TransmissionTimeOffsetObserver : public test::SendTest {
    public:
     TransmissionTimeOffsetObserver()
-        : SendTest(kDefaultTimeoutMs),
-          encoder_(Clock::GetRealTimeClock(), kEncodeDelayMs) {
+        : SendTest(kDefaultTimeoutMs), encoder_factory_([]() {
+            return rtc::MakeUnique<test::DelayedEncoder>(
+                Clock::GetRealTimeClock(), kEncodeDelayMs);
+          }) {
       EXPECT_TRUE(parser_->RegisterRtpHeaderExtension(
           kRtpExtensionTransmissionTimeOffset, test::kTOffsetExtensionId));
     }
@@ -222,7 +226,7 @@
         VideoSendStream::Config* send_config,
         std::vector<VideoReceiveStream::Config>* receive_configs,
         VideoEncoderConfig* encoder_config) override {
-      send_config->encoder_settings.encoder = &encoder_;
+      send_config->encoder_settings.encoder_factory = &encoder_factory_;
       send_config->rtp.extensions.clear();
       send_config->rtp.extensions.push_back(RtpExtension(
           RtpExtension::kTimestampOffsetUri, test::kTOffsetExtensionId));
@@ -232,7 +236,7 @@
       EXPECT_TRUE(Wait()) << "Timed out while waiting for a single RTP packet.";
     }
 
-    test::DelayedEncoder encoder_;
+    test::FunctionVideoEncoderFactory encoder_factory_;
   } test;
 
   RunBaseTest(&test);
@@ -243,7 +247,10 @@
   class TransportWideSequenceNumberObserver : public test::SendTest {
    public:
     TransportWideSequenceNumberObserver()
-        : SendTest(kDefaultTimeoutMs), encoder_(Clock::GetRealTimeClock()) {
+        : SendTest(kDefaultTimeoutMs), encoder_factory_([]() {
+            return rtc::MakeUnique<test::FakeEncoder>(
+                Clock::GetRealTimeClock());
+          }) {
       EXPECT_TRUE(parser_->RegisterRtpHeaderExtension(
           kRtpExtensionTransportSequenceNumber, kExtensionId));
     }
@@ -266,14 +273,14 @@
         VideoSendStream::Config* send_config,
         std::vector<VideoReceiveStream::Config>* receive_configs,
         VideoEncoderConfig* encoder_config) override {
-      send_config->encoder_settings.encoder = &encoder_;
+      send_config->encoder_settings.encoder_factory = &encoder_factory_;
     }
 
     void PerformTest() override {
       EXPECT_TRUE(Wait()) << "Timed out while waiting for a single RTP packet.";
     }
 
-    test::FakeEncoder encoder_;
+    test::FunctionVideoEncoderFactory encoder_factory_;
   } test;
 
   RunBaseTest(&test);
@@ -431,9 +438,9 @@
                  bool expect_red,
                  bool expect_ulpfec,
                  const std::string& codec,
-                 VideoEncoder* encoder)
+                 VideoEncoderFactory* encoder_factory)
       : EndToEndTest(kTimeoutMs),
-        encoder_(encoder),
+        encoder_factory_(encoder_factory),
         payload_name_(codec),
         use_nack_(use_nack),
         expect_red_(expect_red),
@@ -531,7 +538,7 @@
           (*receive_configs)[0].rtp.nack.rtp_history_ms =
               VideoSendStreamTest::kNackRtpHistoryMs;
     }
-    send_config->encoder_settings.encoder = encoder_;
+    send_config->encoder_settings.encoder_factory = encoder_factory_;
     send_config->rtp.payload_name = payload_name_;
     send_config->rtp.ulpfec.red_payload_type =
         VideoSendStreamTest::kRedPayloadType;
@@ -556,7 +563,7 @@
         << "Timed out waiting for ULPFEC and/or media packets.";
   }
 
-  VideoEncoder* const encoder_;
+  VideoEncoderFactory* encoder_factory_;
   std::string payload_name_;
   const bool use_nack_;
   const bool expect_red_;
@@ -568,14 +575,16 @@
 };
 
 TEST_F(VideoSendStreamTest, SupportsUlpfecWithExtensions) {
-  std::unique_ptr<VideoEncoder> encoder(VP8Encoder::Create());
-  UlpfecObserver test(true, false, true, true, "VP8", encoder.get());
+  test::FunctionVideoEncoderFactory encoder_factory(
+      []() { return VP8Encoder::Create(); });
+  UlpfecObserver test(true, false, true, true, "VP8", &encoder_factory);
   RunBaseTest(&test);
 }
 
 TEST_F(VideoSendStreamTest, SupportsUlpfecWithoutExtensions) {
-  std::unique_ptr<VideoEncoder> encoder(VP8Encoder::Create());
-  UlpfecObserver test(false, false, true, true, "VP8", encoder.get());
+  test::FunctionVideoEncoderFactory encoder_factory(
+      []() { return VP8Encoder::Create(); });
+  UlpfecObserver test(false, false, true, true, "VP8", &encoder_factory);
   RunBaseTest(&test);
 }
 
@@ -588,8 +597,9 @@
 };
 
 TEST_F(VideoSendStreamWithoutUlpfecTest, NoUlpfecIfDisabledThroughFieldTrial) {
-  std::unique_ptr<VideoEncoder> encoder(VP8Encoder::Create());
-  UlpfecObserver test(false, false, true, false, "VP8", encoder.get());
+  test::FunctionVideoEncoderFactory encoder_factory(
+      []() { return VP8Encoder::Create(); });
+  UlpfecObserver test(false, false, true, false, "VP8", &encoder_factory);
   RunBaseTest(&test);
 }
 
@@ -598,40 +608,46 @@
 // bandwidth since the receiver has to wait for FEC retransmissions to determine
 // that the received state is actually decodable.
 TEST_F(VideoSendStreamTest, DoesNotUtilizeUlpfecForH264WithNackEnabled) {
-  std::unique_ptr<VideoEncoder> encoder(
-      new test::FakeH264Encoder(Clock::GetRealTimeClock()));
-  UlpfecObserver test(false, true, true, false, "H264", encoder.get());
+  test::FunctionVideoEncoderFactory encoder_factory([]() {
+    return rtc::MakeUnique<test::FakeH264Encoder>(Clock::GetRealTimeClock());
+  });
+  UlpfecObserver test(false, true, true, false, "H264", &encoder_factory);
   RunBaseTest(&test);
 }
 
 // Without retransmissions FEC for H264 is fine.
 TEST_F(VideoSendStreamTest, DoesUtilizeUlpfecForH264WithoutNackEnabled) {
-  std::unique_ptr<VideoEncoder> encoder(
-      new test::FakeH264Encoder(Clock::GetRealTimeClock()));
-  UlpfecObserver test(false, false, true, true, "H264", encoder.get());
+  test::FunctionVideoEncoderFactory encoder_factory([]() {
+    return rtc::MakeUnique<test::FakeH264Encoder>(Clock::GetRealTimeClock());
+  });
+  UlpfecObserver test(false, false, true, true, "H264", &encoder_factory);
   RunBaseTest(&test);
 }
 
 // Disabled as flaky, see https://crbug.com/webrtc/7285 for details.
 TEST_F(VideoSendStreamTest, DISABLED_DoesUtilizeUlpfecForVp8WithNackEnabled) {
-  std::unique_ptr<VideoEncoder> encoder(VP8Encoder::Create());
-  UlpfecObserver test(false, true, true, true, "VP8", encoder.get());
+  test::FunctionVideoEncoderFactory encoder_factory(
+      []() { return VP8Encoder::Create(); });
+  UlpfecObserver test(false, true, true, true, "VP8", &encoder_factory);
   RunBaseTest(&test);
 }
 
 #if !defined(RTC_DISABLE_VP9)
 // Disabled as flaky, see https://crbug.com/webrtc/7285 for details.
 TEST_F(VideoSendStreamTest, DISABLED_DoesUtilizeUlpfecForVp9WithNackEnabled) {
-  std::unique_ptr<VideoEncoder> encoder(VP9Encoder::Create());
-  UlpfecObserver test(false, true, true, true, "VP9", encoder.get());
+  test::FunctionVideoEncoderFactory encoder_factory(
+      []() { return VP9Encoder::Create(); });
+  UlpfecObserver test(false, true, true, true, "VP9", &encoder_factory);
   RunBaseTest(&test);
 }
 #endif  // !defined(RTC_DISABLE_VP9)
 
 TEST_F(VideoSendStreamTest, SupportsUlpfecWithMultithreadedH264) {
-  std::unique_ptr<VideoEncoder> encoder(
-      new test::MultithreadedFakeH264Encoder(Clock::GetRealTimeClock()));
-  UlpfecObserver test(false, false, true, true, "H264", encoder.get());
+  test::FunctionVideoEncoderFactory encoder_factory([]() {
+    return rtc::MakeUnique<test::MultithreadedFakeH264Encoder>(
+        Clock::GetRealTimeClock());
+  });
+  UlpfecObserver test(false, false, true, true, "H264", &encoder_factory);
   RunBaseTest(&test);
 }
 
@@ -642,10 +658,10 @@
   FlexfecObserver(bool header_extensions_enabled,
                   bool use_nack,
                   const std::string& codec,
-                  VideoEncoder* encoder,
+                  VideoEncoderFactory* encoder_factory,
                   size_t num_video_streams)
       : EndToEndTest(VideoSendStreamTest::kDefaultTimeoutMs),
-        encoder_(encoder),
+        encoder_factory_(encoder_factory),
         payload_name_(codec),
         use_nack_(use_nack),
         sent_media_(false),
@@ -709,7 +725,7 @@
           (*receive_configs)[0].rtp.nack.rtp_history_ms =
               VideoSendStreamTest::kNackRtpHistoryMs;
     }
-    send_config->encoder_settings.encoder = encoder_;
+    send_config->encoder_settings.encoder_factory = encoder_factory_;
     send_config->rtp.payload_name = payload_name_;
     if (header_extensions_enabled_) {
       send_config->rtp.extensions.push_back(RtpExtension(
@@ -727,7 +743,7 @@
         << "Timed out waiting for FlexFEC and/or media packets.";
   }
 
-  VideoEncoder* const encoder_;
+  VideoEncoderFactory* encoder_factory_;
   std::string payload_name_;
   const bool use_nack_;
   bool sent_media_;
@@ -737,61 +753,72 @@
 };
 
 TEST_F(VideoSendStreamTest, SupportsFlexfecVp8) {
-  std::unique_ptr<VideoEncoder> encoder(VP8Encoder::Create());
-  FlexfecObserver test(false, false, "VP8", encoder.get(), 1);
+  test::FunctionVideoEncoderFactory encoder_factory(
+      []() { return VP8Encoder::Create(); });
+  FlexfecObserver test(false, false, "VP8", &encoder_factory, 1);
   RunBaseTest(&test);
 }
 
 TEST_F(VideoSendStreamTest, SupportsFlexfecSimulcastVp8) {
-  std::unique_ptr<VideoEncoder> encoder(VP8Encoder::Create());
-  FlexfecObserver test(false, false, "VP8", encoder.get(), 2);
+  test::FunctionVideoEncoderFactory encoder_factory(
+      []() { return VP8Encoder::Create(); });
+  FlexfecObserver test(false, false, "VP8", &encoder_factory, 2);
   RunBaseTest(&test);
 }
 
 TEST_F(VideoSendStreamTest, SupportsFlexfecWithNackVp8) {
-  std::unique_ptr<VideoEncoder> encoder(VP8Encoder::Create());
-  FlexfecObserver test(false, true, "VP8", encoder.get(), 1);
+  test::FunctionVideoEncoderFactory encoder_factory(
+      []() { return VP8Encoder::Create(); });
+  FlexfecObserver test(false, true, "VP8", &encoder_factory, 1);
   RunBaseTest(&test);
 }
 
 TEST_F(VideoSendStreamTest, SupportsFlexfecWithRtpExtensionsVp8) {
-  std::unique_ptr<VideoEncoder> encoder(VP8Encoder::Create());
-  FlexfecObserver test(true, false, "VP8", encoder.get(), 1);
+  test::FunctionVideoEncoderFactory encoder_factory(
+      []() { return VP8Encoder::Create(); });
+  FlexfecObserver test(true, false, "VP8", &encoder_factory, 1);
   RunBaseTest(&test);
 }
 
 #if !defined(RTC_DISABLE_VP9)
 TEST_F(VideoSendStreamTest, SupportsFlexfecVp9) {
-  std::unique_ptr<VideoEncoder> encoder(VP9Encoder::Create());
-  FlexfecObserver test(false, false, "VP9", encoder.get(), 1);
+  test::FunctionVideoEncoderFactory encoder_factory(
+      []() { return VP9Encoder::Create(); });
+  FlexfecObserver test(false, false, "VP9", &encoder_factory, 1);
   RunBaseTest(&test);
 }
 
 TEST_F(VideoSendStreamTest, SupportsFlexfecWithNackVp9) {
-  std::unique_ptr<VideoEncoder> encoder(VP9Encoder::Create());
-  FlexfecObserver test(false, true, "VP9", encoder.get(), 1);
+  test::FunctionVideoEncoderFactory encoder_factory(
+      []() { return VP9Encoder::Create(); });
+  FlexfecObserver test(false, true, "VP9", &encoder_factory, 1);
   RunBaseTest(&test);
 }
 #endif  // defined(RTC_DISABLE_VP9)
 
 TEST_F(VideoSendStreamTest, SupportsFlexfecH264) {
-  std::unique_ptr<VideoEncoder> encoder(
-      new test::FakeH264Encoder(Clock::GetRealTimeClock()));
-  FlexfecObserver test(false, false, "H264", encoder.get(), 1);
+  test::FunctionVideoEncoderFactory encoder_factory([]() {
+    return rtc::MakeUnique<test::FakeH264Encoder>(Clock::GetRealTimeClock());
+  });
+  FlexfecObserver test(false, false, "H264", &encoder_factory, 1);
   RunBaseTest(&test);
 }
 
 TEST_F(VideoSendStreamTest, SupportsFlexfecWithNackH264) {
-  std::unique_ptr<VideoEncoder> encoder(
-      new test::FakeH264Encoder(Clock::GetRealTimeClock()));
-  FlexfecObserver test(false, true, "H264", encoder.get(), 1);
+  test::FunctionVideoEncoderFactory encoder_factory([]() {
+    return rtc::MakeUnique<test::FakeH264Encoder>(Clock::GetRealTimeClock());
+  });
+  FlexfecObserver test(false, true, "H264", &encoder_factory, 1);
   RunBaseTest(&test);
 }
 
 TEST_F(VideoSendStreamTest, SupportsFlexfecWithMultithreadedH264) {
-  std::unique_ptr<VideoEncoder> encoder(
-      new test::MultithreadedFakeH264Encoder(Clock::GetRealTimeClock()));
-  FlexfecObserver test(false, false, "H264", encoder.get(), 1);
+  test::FunctionVideoEncoderFactory encoder_factory([]() {
+    return rtc::MakeUnique<test::MultithreadedFakeH264Encoder>(
+        Clock::GetRealTimeClock());
+  });
+
+  FlexfecObserver test(false, false, "H264", &encoder_factory, 1);
   RunBaseTest(&test);
 }
 
@@ -921,6 +948,7 @@
                            bool use_fec)
         : SendTest(kLongTimeoutMs),
           encoder_(stop),
+          encoder_factory_(&encoder_),
           max_packet_size_(max_packet_size),
           stop_size_(stop_size),
           test_generic_packetization_(test_generic_packetization),
@@ -1076,8 +1104,7 @@
 
       if (!test_generic_packetization_)
         send_config->rtp.payload_name = "VP8";
-
-      send_config->encoder_settings.encoder = &encoder_;
+      send_config->encoder_settings.encoder_factory = &encoder_factory_;
       send_config->rtp.max_packet_size = kMaxPacketSize;
       send_config->post_encode_callback = this;
 
@@ -1120,6 +1147,7 @@
 
     std::unique_ptr<internal::TransportAdapter> transport_adapter_;
     test::ConfigurableFrameSizeEncoder encoder_;
+    test::EncoderProxyFactory encoder_factory_;
 
     const size_t max_packet_size_;
     const size_t stop_size_;
@@ -1908,11 +1936,12 @@
 
   test::NullTransport transport;
   EncoderObserver encoder;
+  test::EncoderProxyFactory encoder_factory(&encoder);
 
-  task_queue_.SendTask([this, &transport, &encoder]() {
+  task_queue_.SendTask([this, &transport, &encoder_factory]() {
     CreateSenderCall(Call::Config(event_log_.get()));
     CreateSendConfig(1, 0, 0, &transport);
-    video_send_config_.encoder_settings.encoder = &encoder;
+    video_send_config_.encoder_settings.encoder_factory = &encoder_factory;
     CreateVideoStreams();
     CreateFrameGeneratorCapturer(kDefaultFramerate, kDefaultWidth,
                                  kDefaultHeight);
@@ -1984,13 +2013,21 @@
       bitrate_config);
 
   StartBitrateObserver encoder;
-  video_send_config_.encoder_settings.encoder = &encoder;
+  test::EncoderProxyFactory encoder_factory(&encoder);
   // Since this test does not use a capturer, set |internal_source| = true.
   // Encoder configuration is otherwise updated on the next video frame.
-  video_send_config_.encoder_settings.internal_source = true;
+  encoder_factory.SetHasInternalSource(true);
+  video_send_config_.encoder_settings.encoder_factory = &encoder_factory;
 
   CreateVideoStreams();
 
+  // Inject a frame, to force encoder creation.
+  video_send_stream_->Start();
+  test::FrameForwarder forwarder;
+  video_send_stream_->SetSource(
+      &forwarder, VideoSendStream::DegradationPreference::kDegradationDisabled);
+  forwarder.IncomingCapturedFrame(CreateVideoFrame(640, 480, 4));
+
   EXPECT_TRUE(encoder.WaitForStartBitrate());
   EXPECT_EQ(video_encoder_config_.max_bitrate_bps / 1000,
             encoder.GetStartBitrateKbps());
@@ -2066,17 +2103,24 @@
 TEST_F(VideoSendStreamTest, VideoSendStreamStopSetEncoderRateToZero) {
   test::NullTransport transport;
   StartStopBitrateObserver encoder;
+  test::EncoderProxyFactory encoder_factory(&encoder);
+  encoder_factory.SetHasInternalSource(true);
+  test::FrameForwarder forwarder;
 
-  task_queue_.SendTask([this, &transport, &encoder]() {
+  task_queue_.SendTask([this, &transport, &encoder_factory, &forwarder]() {
     CreateSenderCall(Call::Config(event_log_.get()));
     CreateSendConfig(1, 0, 0, &transport);
 
     sender_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkUp);
-
-    video_send_config_.encoder_settings.encoder = &encoder;
-    video_send_config_.encoder_settings.internal_source = true;
+    video_send_config_.encoder_settings.encoder_factory = &encoder_factory;
 
     CreateVideoStreams();
+    // Inject a frame, to force encoder creation.
+    video_send_stream_->Start();
+    video_send_stream_->SetSource(
+        &forwarder,
+        VideoSendStream::DegradationPreference::kDegradationDisabled);
+    forwarder.IncomingCapturedFrame(CreateVideoFrame(640, 480, 4));
   });
 
   EXPECT_TRUE(encoder.WaitForEncoderInit());
@@ -2109,19 +2153,28 @@
 TEST_F(VideoSendStreamTest, VideoSendStreamUpdateActiveSimulcastLayers) {
   test::NullTransport transport;
   StartStopBitrateObserver encoder;
+  test::EncoderProxyFactory encoder_factory(&encoder);
+  encoder_factory.SetHasInternalSource(true);
+  test::FrameForwarder forwarder;
 
-  task_queue_.SendTask([this, &transport, &encoder]() {
+  task_queue_.SendTask([this, &transport, &encoder_factory, &forwarder]() {
     CreateSenderCall(Call::Config(event_log_.get()));
     // Create two simulcast streams.
     CreateSendConfig(2, 0, 0, &transport);
 
     sender_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkUp);
+    video_send_config_.encoder_settings.encoder_factory = &encoder_factory;
 
-    video_send_config_.encoder_settings.encoder = &encoder;
-    video_send_config_.encoder_settings.internal_source = true;
     video_send_config_.rtp.payload_name = "VP8";
 
     CreateVideoStreams();
+
+    // Inject a frame, to force encoder creation.
+    video_send_stream_->Start();
+    video_send_stream_->SetSource(
+        &forwarder,
+        VideoSendStream::DegradationPreference::kDegradationDisabled);
+    forwarder.IncomingCapturedFrame(CreateVideoFrame(640, 480, 4));
   });
 
   EXPECT_TRUE(encoder.WaitForEncoderInit());
@@ -2270,7 +2323,8 @@
           initialized_(false),
           callback_registered_(false),
           num_releases_(0),
-          released_(false) {}
+          released_(false),
+          encoder_factory_(this) {}
 
     bool IsReleased() {
       rtc::CritScope lock(&crit_);
@@ -2346,7 +2400,7 @@
         VideoSendStream::Config* send_config,
         std::vector<VideoReceiveStream::Config>* receive_configs,
         VideoEncoderConfig* encoder_config) override {
-      send_config->encoder_settings.encoder = this;
+      send_config->encoder_settings.encoder_factory = &encoder_factory_;
       encoder_config_ = encoder_config->Copy();
     }
 
@@ -2375,6 +2429,7 @@
     bool callback_registered_ RTC_GUARDED_BY(crit_);
     size_t num_releases_ RTC_GUARDED_BY(crit_);
     bool released_ RTC_GUARDED_BY(crit_);
+    test::EncoderProxyFactory encoder_factory_;
     VideoEncoderConfig encoder_config_;
   } test_encoder(&task_queue_);
 
@@ -2393,14 +2448,15 @@
           FakeEncoder(Clock::GetRealTimeClock()),
           init_encode_event_(false, false),
           num_initializations_(0),
-          stream_(nullptr) {}
+          stream_(nullptr),
+          encoder_factory_(this) {}
 
    private:
     void ModifyVideoConfigs(
         VideoSendStream::Config* send_config,
         std::vector<VideoReceiveStream::Config>* receive_configs,
         VideoEncoderConfig* encoder_config) override {
-      send_config->encoder_settings.encoder = this;
+      send_config->encoder_settings.encoder_factory = &encoder_factory_;
       encoder_config->max_bitrate_bps = kFirstMaxBitrateBps;
       encoder_config_ = encoder_config->Copy();
     }
@@ -2444,6 +2500,7 @@
     rtc::Event init_encode_event_;
     size_t num_initializations_;
     VideoSendStream* stream_;
+    test::EncoderProxyFactory encoder_factory_;
     VideoEncoderConfig encoder_config_;
   } test;
 
@@ -2463,7 +2520,8 @@
         codec_name_(codec_name),
         init_encode_event_(false, false),
         num_initializations_(0),
-        stream_(nullptr) {
+        stream_(nullptr),
+        encoder_factory_(this) {
     InitCodecSpecifics();
   }
 
@@ -2492,7 +2550,7 @@
       VideoSendStream::Config* send_config,
       std::vector<VideoReceiveStream::Config>* receive_configs,
       VideoEncoderConfig* encoder_config) override {
-    send_config->encoder_settings.encoder = this;
+    send_config->encoder_settings.encoder_factory = &encoder_factory_;
     send_config->rtp.payload_name = codec_name_;
 
     encoder_config->codec_type = video_codec_type_;
@@ -2552,6 +2610,7 @@
   rtc::Event init_encode_event_;
   size_t num_initializations_;
   VideoSendStream* stream_;
+  test::EncoderProxyFactory encoder_factory_;
   VideoEncoderConfig encoder_config_;
 };
 
@@ -2738,7 +2797,8 @@
    public:
     ScreencastTargetBitrateTest()
         : SendTest(kDefaultTimeoutMs),
-          test::FakeEncoder(Clock::GetRealTimeClock()) {}
+          test::FakeEncoder(Clock::GetRealTimeClock()),
+          encoder_factory_(this) {}
 
    private:
     int32_t InitEncode(const VideoCodec* config,
@@ -2754,7 +2814,7 @@
         VideoSendStream::Config* send_config,
         std::vector<VideoReceiveStream::Config>* receive_configs,
         VideoEncoderConfig* encoder_config) override {
-      send_config->encoder_settings.encoder = this;
+      send_config->encoder_settings.encoder_factory = &encoder_factory_;
       EXPECT_EQ(1u, encoder_config->number_of_streams);
       encoder_config->video_stream_factory =
           new rtc::RefCountedObject<VideoStreamFactory>();
@@ -2765,6 +2825,7 @@
       EXPECT_TRUE(Wait())
           << "Timed out while waiting for the encoder to be initialized.";
     }
+    test::EncoderProxyFactory encoder_factory_;
   } test;
 
   RunBaseTest(&test);
@@ -2792,7 +2853,8 @@
           target_bitrate_(0),
           num_initializations_(0),
           call_(nullptr),
-          send_stream_(nullptr) {}
+          send_stream_(nullptr),
+          encoder_factory_(this) {}
 
    private:
     int32_t InitEncode(const VideoCodec* codecSettings,
@@ -2882,7 +2944,7 @@
         VideoSendStream::Config* send_config,
         std::vector<VideoReceiveStream::Config>* receive_configs,
         VideoEncoderConfig* encoder_config) override {
-      send_config->encoder_settings.encoder = this;
+      send_config->encoder_settings.encoder_factory = &encoder_factory_;
       // Set bitrates lower/higher than min/max to make sure they are properly
       // capped.
       encoder_config->max_bitrate_bps = kMaxBitrateKbps * 1000;
@@ -2945,6 +3007,7 @@
     int num_initializations_;
     webrtc::Call* call_;
     webrtc::VideoSendStream* send_stream_;
+    test::EncoderProxyFactory encoder_factory_;
     webrtc::VideoEncoderConfig encoder_config_;
   } test(&task_queue_);
 
@@ -2965,7 +3028,8 @@
     ScreencastTargetBitrateTest()
         : SendTest(kDefaultTimeoutMs),
           test::FakeEncoder(Clock::GetRealTimeClock()),
-          send_stream_(nullptr) {}
+          send_stream_(nullptr),
+          encoder_factory_(this) {}
 
    private:
     int32_t Encode(const VideoFrame& input_image,
@@ -3003,7 +3067,7 @@
         VideoSendStream::Config* send_config,
         std::vector<VideoReceiveStream::Config>* receive_configs,
         VideoEncoderConfig* encoder_config) override {
-      send_config->encoder_settings.encoder = this;
+      send_config->encoder_settings.encoder_factory = &encoder_factory_;
       EXPECT_EQ(kNumStreams, encoder_config->number_of_streams);
     }
 
@@ -3033,6 +3097,7 @@
     }
 
     VideoSendStream* send_stream_;
+    test::EncoderProxyFactory encoder_factory_;
   } test;
 
   RunBaseTest(&test);
@@ -3043,7 +3108,7 @@
  public:
   Vp9HeaderObserver()
       : SendTest(VideoSendStreamTest::kLongTimeoutMs),
-        vp9_encoder_(VP9Encoder::Create()),
+        encoder_factory_([]() { return VP9Encoder::Create(); }),
         vp9_settings_(VideoEncoder::GetDefaultVp9Settings()),
         packets_sent_(0),
         frames_sent_(0),
@@ -3084,7 +3149,7 @@
       VideoSendStream::Config* send_config,
       std::vector<VideoReceiveStream::Config>* receive_configs,
       VideoEncoderConfig* encoder_config) override {
-    send_config->encoder_settings.encoder = vp9_encoder_.get();
+    send_config->encoder_settings.encoder_factory = &encoder_factory_;
     send_config->rtp.payload_name = "VP9";
     send_config->rtp.payload_type = kVp9PayloadType;
     ModifyVideoConfigsHook(send_config, receive_configs, encoder_config);
@@ -3346,7 +3411,7 @@
     VerifyTl0Idx(vp9);
   }
 
-  std::unique_ptr<VP9Encoder> vp9_encoder_;
+  test::FunctionVideoEncoderFactory encoder_factory_;
   VideoCodecVP9 vp9_settings_;
   webrtc::VideoEncoderConfig encoder_config_;
   RTPHeader last_header_;
@@ -3593,6 +3658,7 @@
         : EndToEndTest(test::CallTest::kDefaultTimeoutMs),
           FakeEncoder(Clock::GetRealTimeClock()),
           task_queue_(task_queue),
+          encoder_factory_(this),
           call_(nullptr),
           max_bitrate_bps_(0),
           first_packet_sent_(false),
@@ -3619,7 +3685,7 @@
         std::vector<VideoReceiveStream::Config>* receive_configs,
         VideoEncoderConfig* encoder_config) override {
       send_config->rtp.max_packet_size = 1200;
-      send_config->encoder_settings.encoder = this;
+      send_config->encoder_settings.encoder_factory = &encoder_factory_;
       EXPECT_FALSE(send_config->rtp.extensions.empty());
     }
 
@@ -3646,7 +3712,8 @@
       // At a bitrate of 60kbps with a packet size of 1200B video and an
       // overhead of 40B per packet video produces 2240bps overhead.
       // So the encoder BW should be set to 57760bps.
-      bitrate_changed_event_.Wait(VideoSendStreamTest::kDefaultTimeoutMs);
+      EXPECT_TRUE(
+          bitrate_changed_event_.Wait(VideoSendStreamTest::kDefaultTimeoutMs));
       {
         rtc::CritScope lock(&crit_);
         EXPECT_LE(max_bitrate_bps_, 57760u);
@@ -3655,6 +3722,7 @@
 
    private:
     test::SingleThreadedTaskQueueForTesting* const task_queue_;
+    test::EncoderProxyFactory encoder_factory_;
     Call* call_;
     rtc::CriticalSection crit_;
     uint32_t max_bitrate_bps_ RTC_GUARDED_BY(&crit_);
diff --git a/video/video_stream_encoder.cc b/video/video_stream_encoder.cc
index 952d4ed..7bb17b0 100644
--- a/video/video_stream_encoder.cc
+++ b/video/video_stream_encoder.cc
@@ -91,10 +91,11 @@
 // out). This should effectively turn off CPU adaptations for systems that
 // remotely cope with the load right now.
 CpuOveruseOptions GetCpuOveruseOptions(
-    const VideoSendStream::Config::EncoderSettings& settings) {
+    const VideoSendStream::Config::EncoderSettings& settings,
+    bool full_overuse_time) {
   CpuOveruseOptions options;
 
-  if (settings.full_overuse_time) {
+  if (full_overuse_time) {
     options.low_encode_usage_threshold_percent = 150;
     options.high_encode_usage_threshold_percent = 200;
   }
@@ -338,6 +339,7 @@
       pre_encode_callback_(pre_encode_callback),
       max_framerate_(-1),
       pending_encoder_reconfiguration_(false),
+      pending_encoder_creation_(false),
       encoder_start_bitrate_bps_(0),
       max_data_payload_length_(0),
       nack_enabled_(false),
@@ -357,13 +359,6 @@
       encoder_queue_("EncoderQueue") {
   RTC_DCHECK(stats_proxy);
   RTC_DCHECK(overuse_detector_);
-  encoder_queue_.PostTask([this] {
-    RTC_DCHECK_RUN_ON(&encoder_queue_);
-    overuse_detector_->StartCheckForOveruse(GetCpuOveruseOptions(settings_),
-                                            this);
-    video_sender_.RegisterExternalEncoder(
-        settings_.encoder, settings_.internal_source);
-  });
 }
 
 VideoStreamEncoder::~VideoStreamEncoder() {
@@ -422,7 +417,10 @@
     degradation_preference_ = degradation_preference;
     bool allow_scaling = IsResolutionScalingEnabled(degradation_preference_);
     initial_rampup_ = allow_scaling ? 0 : kMaxInitialFramedrop;
-    ConfigureQualityScaler();
+
+    stats_proxy_->SetAdaptationStats(GetActiveCounts(kCpu),
+                                     GetActiveCounts(kQuality));
+
     if (!IsFramerateScalingEnabled(degradation_preference) &&
         max_framerate_ != -1) {
       // If frame rate scaling is no longer allowed, remove any potential
@@ -476,6 +474,8 @@
 
   max_data_payload_length_ = max_data_payload_length;
   nack_enabled_ = nack_enabled;
+  pending_encoder_creation_ =
+      (!encoder_ || encoder_config_.video_format != config.video_format);
   encoder_config_ = std::move(config);
   pending_encoder_reconfiguration_ = true;
 
@@ -485,9 +485,6 @@
   // The codec configuration depends on incoming video frame size.
   if (last_frame_info_) {
     ReconfigureEncoder();
-  } else if (settings_.internal_source) {
-    last_frame_info_ = VideoFrameInfo(176, 144, false);
-    ReconfigureEncoder();
   }
 }
 
@@ -528,6 +525,34 @@
   max_framerate_ = codec.maxFramerate;
   RTC_DCHECK_LE(max_framerate_, kMaxFramerateFps);
 
+  // Keep the same encoder, as long as the video_format is unchanged.
+  if (pending_encoder_creation_) {
+    pending_encoder_creation_ = false;
+    if (encoder_) {
+      video_sender_.RegisterExternalEncoder(nullptr, false);
+    }
+
+    encoder_ = settings_.encoder_factory->CreateVideoEncoder(
+        encoder_config_.video_format);
+    // TODO(nisse): What to do if creating the encoder fails? Crash,
+    // or just discard incoming frames?
+    RTC_CHECK(encoder_);
+
+    ConfigureQualityScaler();
+
+    const webrtc::VideoEncoderFactory::CodecInfo info =
+        settings_.encoder_factory->QueryVideoEncoder(
+            encoder_config_.video_format);
+
+    overuse_detector_->StopCheckForOveruse();
+    overuse_detector_->StartCheckForOveruse(
+        GetCpuOveruseOptions(settings_, info.is_hardware_accelerated), this);
+
+    video_sender_.RegisterExternalEncoder(encoder_.get(),
+                                          info.has_internal_source);
+  }
+  // RegisterSendCodec implies an unconditional call to
+  // encoder_->InitEncode().
   bool success = video_sender_.RegisterSendCodec(
                      &codec, number_of_cores_,
                      static_cast<uint32_t>(max_data_payload_length_)) == VCM_OK;
@@ -563,13 +588,11 @@
   int target_framerate = std::min(
       max_framerate_, source_proxy_->GetActiveSinkWants().max_framerate_fps);
   overuse_detector_->OnTargetFramerateUpdated(target_framerate);
-
-  ConfigureQualityScaler();
 }
 
 void VideoStreamEncoder::ConfigureQualityScaler() {
   RTC_DCHECK_RUN_ON(&encoder_queue_);
-  const auto scaling_settings = settings_.encoder->GetScalingSettings();
+  const auto scaling_settings = encoder_->GetScalingSettings();
   const bool quality_scaling_allowed =
       IsResolutionScalingEnabled(degradation_preference_) &&
       scaling_settings.thresholds;
@@ -589,6 +612,8 @@
     initial_rampup_ = kMaxInitialFramedrop;
   }
 
+  // TODO(nisse): Is this still the right place to do this? This is
+  // now called when the encoder is created.
   stats_proxy_->SetAdaptationStats(GetActiveCounts(kCpu),
                                    GetActiveCounts(kQuality));
 }
@@ -723,6 +748,24 @@
                      << ", texture=" << last_frame_info_->is_texture << ".";
   }
 
+  // We have to create then encoder before the frame drop logic,
+  // because the latter depends on encoder_->GetScalingSettings.
+  // According to the testcase
+  // InitialFrameDropOffWhenEncoderDisabledScaling, the return value
+  // from GetScalingSettings should enable or disable the frame drop.
+
+  int64_t now_ms = clock_->TimeInMilliseconds();
+  if (pending_encoder_reconfiguration_) {
+    ReconfigureEncoder();
+    last_parameters_update_ms_.emplace(now_ms);
+  } else if (!last_parameters_update_ms_ ||
+             now_ms - *last_parameters_update_ms_ >=
+                 vcm::VCMProcessTimer::kDefaultProcessIntervalMs) {
+    video_sender_.UpdateChannelParameters(rate_allocator_.get(),
+                                          bitrate_observer_);
+    last_parameters_update_ms_.emplace(now_ms);
+  }
+
   if (DropDueToSize(video_frame.size())) {
     RTC_LOG(LS_INFO) << "Dropping frame. Too large for target bitrate.";
     int count = GetConstAdaptCounter().ResolutionCount(kQuality);
@@ -737,17 +780,6 @@
   }
   initial_rampup_ = kMaxInitialFramedrop;
 
-  int64_t now_ms = clock_->TimeInMilliseconds();
-  if (pending_encoder_reconfiguration_) {
-    ReconfigureEncoder();
-    last_parameters_update_ms_.emplace(now_ms);
-  } else if (!last_parameters_update_ms_ ||
-             now_ms - *last_parameters_update_ms_ >=
-                 vcm::VCMProcessTimer::kDefaultProcessIntervalMs) {
-    video_sender_.UpdateChannelParameters(rate_allocator_.get(),
-                                          bitrate_observer_);
-    last_parameters_update_ms_.emplace(now_ms);
-  }
 
   if (EncoderPaused()) {
     if (pending_frame_)
@@ -971,7 +1003,7 @@
       bool min_pixels_reached = false;
       if (!source_proxy_->RequestResolutionLowerThan(
               adaptation_request.input_pixel_count_,
-              settings_.encoder->GetScalingSettings().min_pixels_per_frame,
+              encoder_->GetScalingSettings().min_pixels_per_frame,
               &min_pixels_reached)) {
         if (min_pixels_reached)
           stats_proxy_->OnMinPixelLimitReached();
diff --git a/video/video_stream_encoder.h b/video/video_stream_encoder.h
index a81160e..ac4f254 100644
--- a/video/video_stream_encoder.h
+++ b/video/video_stream_encoder.h
@@ -231,6 +231,8 @@
   rtc::ThreadChecker thread_checker_;
 
   VideoEncoderConfig encoder_config_ RTC_GUARDED_BY(&encoder_queue_);
+  std::unique_ptr<VideoEncoder> encoder_ RTC_GUARDED_BY(&encoder_queue_)
+      RTC_PT_GUARDED_BY(&encoder_queue_);
   std::unique_ptr<VideoBitrateAllocator> rate_allocator_
       RTC_GUARDED_BY(&encoder_queue_)
       RTC_PT_GUARDED_BY(&encoder_queue_);
@@ -241,6 +243,9 @@
   // Set when ConfigureEncoder has been called in order to lazy reconfigure the
   // encoder on the next frame.
   bool pending_encoder_reconfiguration_ RTC_GUARDED_BY(&encoder_queue_);
+  // Set when configuration must create a new encoder object, e.g.,
+  // because of a codec change.
+  bool pending_encoder_creation_ RTC_GUARDED_BY(&encoder_queue_);
   rtc::Optional<VideoFrameInfo> last_frame_info_
       RTC_GUARDED_BY(&encoder_queue_);
   int crop_width_ RTC_GUARDED_BY(&encoder_queue_);
diff --git a/video/video_stream_encoder_unittest.cc b/video/video_stream_encoder_unittest.cc
index 8a6d4e1..4b39223 100644
--- a/video/video_stream_encoder_unittest.cc
+++ b/video/video_stream_encoder_unittest.cc
@@ -21,6 +21,7 @@
 #include "rtc_base/logging.h"
 #include "system_wrappers/include/metrics_default.h"
 #include "system_wrappers/include/sleep.h"
+#include "test/encoder_proxy_factory.h"
 #include "test/encoder_settings.h"
 #include "test/fake_encoder.h"
 #include "test/frame_generator.h"
@@ -83,6 +84,8 @@
     return last_target_framerate_fps_;
   }
 
+  CpuOveruseOptions GetOptions() { return options_; }
+
  private:
   rtc::CriticalSection lock_;
   int last_target_framerate_fps_ RTC_GUARDED_BY(lock_);
@@ -272,6 +275,7 @@
         codec_height_(240),
         max_framerate_(30),
         fake_encoder_(),
+        encoder_factory_(&fake_encoder_),
         stats_proxy_(new MockableSendStatisticsProxy(
             Clock::GetRealTimeClock(),
             video_send_config_,
@@ -281,7 +285,7 @@
   void SetUp() override {
     metrics::Reset();
     video_send_config_ = VideoSendStream::Config(nullptr);
-    video_send_config_.encoder_settings.encoder = &fake_encoder_;
+    video_send_config_.encoder_settings.encoder_factory = &encoder_factory_;
     video_send_config_.rtp.payload_name = "FAKE";
     video_send_config_.rtp.payload_type = 125;
 
@@ -683,6 +687,7 @@
   int codec_height_;
   int max_framerate_;
   TestEncoder fake_encoder_;
+  test::EncoderProxyFactory encoder_factory_;
   std::unique_ptr<MockableSendStatisticsProxy> stats_proxy_;
   TestSink sink_;
   AdaptingFrameForwarder video_source_;
@@ -1437,11 +1442,16 @@
   EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_resolution);
   EXPECT_EQ(1, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
 
-  // Set source with adaptation still enabled but quality scaler is off.
+  // Leave source unchanged, but disable quality scaler.
   fake_encoder_.SetQualityScaling(false);
-  video_stream_encoder_->SetSource(
-      &video_source_,
-      VideoSendStream::DegradationPreference::kMaintainFramerate);
+
+  VideoEncoderConfig video_encoder_config;
+  test::FillEncoderConfiguration(kVideoCodecVP8, 1, &video_encoder_config);
+  // Make format different, to force recreation of encoder.
+  video_encoder_config.video_format.parameters["foo"] = "foo";
+  video_stream_encoder_->ConfigureEncoder(std::move(video_encoder_config),
+                                          kMaxPayloadLength,
+                                          true /* nack_enabled */);
 
   video_source_.IncomingCapturedFrame(CreateFrame(4, kWidth, kHeight));
   WaitForEncodedFrame(4);
@@ -2516,6 +2526,14 @@
   const int kWidth = 640;
   const int kHeight = 360;
   fake_encoder_.SetQualityScaling(false);
+
+  VideoEncoderConfig video_encoder_config;
+  test::FillEncoderConfiguration(kVideoCodecVP8, 1, &video_encoder_config);
+  // Make format different, to force recreation of encoder.
+  video_encoder_config.video_format.parameters["foo"] = "foo";
+  video_stream_encoder_->ConfigureEncoder(std::move(video_encoder_config),
+                                          kMaxPayloadLength,
+                                          true /* nack_enabled */);
   video_stream_encoder_->OnBitrateUpdated(kLowTargetBitrateBps, 0, 0);
 
   // Force quality scaler reconfiguration by resetting the source.
@@ -3314,4 +3332,44 @@
   video_stream_encoder_->Stop();
 }
 
+TEST_F(VideoStreamEncoderTest,
+       DefaultCpuAdaptationThresholdsForSoftwareEncoder) {
+  const int kFrameWidth = 1280;
+  const int kFrameHeight = 720;
+  const CpuOveruseOptions default_options;
+  video_stream_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
+  video_source_.IncomingCapturedFrame(
+      CreateFrame(1, kFrameWidth, kFrameHeight));
+  WaitForEncodedFrame(1);
+  EXPECT_EQ(video_stream_encoder_->overuse_detector_proxy_->GetOptions()
+                .low_encode_usage_threshold_percent,
+            default_options.low_encode_usage_threshold_percent);
+  EXPECT_EQ(video_stream_encoder_->overuse_detector_proxy_->GetOptions()
+                .high_encode_usage_threshold_percent,
+            default_options.high_encode_usage_threshold_percent);
+  video_stream_encoder_->Stop();
+}
+
+TEST_F(VideoStreamEncoderTest,
+       HigherCpuAdaptationThresholdsForHardwareEncoder) {
+  const int kFrameWidth = 1280;
+  const int kFrameHeight = 720;
+  CpuOveruseOptions hardware_options;
+  hardware_options.low_encode_usage_threshold_percent = 150;
+  hardware_options.high_encode_usage_threshold_percent = 200;
+  encoder_factory_.SetIsHardwareAccelerated(true);
+
+  video_stream_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
+  video_source_.IncomingCapturedFrame(
+      CreateFrame(1, kFrameWidth, kFrameHeight));
+  WaitForEncodedFrame(1);
+  EXPECT_EQ(video_stream_encoder_->overuse_detector_proxy_->GetOptions()
+                .low_encode_usage_threshold_percent,
+            hardware_options.low_encode_usage_threshold_percent);
+  EXPECT_EQ(video_stream_encoder_->overuse_detector_proxy_->GetOptions()
+                .high_encode_usage_threshold_percent,
+            hardware_options.high_encode_usage_threshold_percent);
+  video_stream_encoder_->Stop();
+}
+
 }  // namespace webrtc