Revert of Let ViEEncoder handle resolution changes. (patchset #17 id:340001 of https://codereview.webrtc.org/2351633002/ )

Reason for revert:
Fails on a content_browsertest (and also webrtc_perf?)

https://build.chromium.org/p/chromium.webrtc.fyi/builders/Mac%20Tester/builds/34336

https://build.chromium.org/p/client.webrtc/builders/Linux64%20Release%20%5Blarge%20tests%5D/builds/9091/steps/webrtc_perf_tests/logs/stdio
[  FAILED  ] FullStackTest.ParisQcifWithoutPacketLoss (59436 ms)

Original issue's description:
> Let ViEEncoder handle resolution changes.
>
> This cl move codec reconfiguration due to video frame size changes from WebRtcVideoSendStream to ViEEncoder.
>
> With this change, many variables in WebRtcVideoSendStream no longer need to be locked.
>
> BUG=webrtc:5687, webrtc:6371, webrtc:5332
>
> Committed: https://crrev.com/26105b41b4f97642ee30cb067dc786c2737709ad
> Cr-Commit-Position: refs/heads/master@{#14445}

TBR=sprang@webrtc.org,mflodman@webrtc.org,stefan@webrtc.org
# Skipping CQ checks because original CL landed less than 1 days ago.
NOPRESUBMIT=true
NOTREECHECKS=true
NOTRY=true
BUG=webrtc:5687, webrtc:6371, webrtc:5332

Review-Url: https://codereview.webrtc.org/2383493005
Cr-Commit-Position: refs/heads/master@{#14447}
diff --git a/webrtc/api/videocapturertracksource_unittest.cc b/webrtc/api/videocapturertracksource_unittest.cc
index d8f4b0c..48133b1 100644
--- a/webrtc/api/videocapturertracksource_unittest.cc
+++ b/webrtc/api/videocapturertracksource_unittest.cc
@@ -184,7 +184,7 @@
   ASSERT_TRUE(format != NULL);
   EXPECT_EQ(352, format->width);
   EXPECT_EQ(288, format->height);
-  EXPECT_EQ(5, format->framerate());
+  EXPECT_EQ(30, format->framerate());
 }
 
 // Test that the capture output is 720P if the camera support it and the
@@ -401,7 +401,7 @@
   ASSERT_TRUE(format != NULL);
   EXPECT_EQ(352, format->width);
   EXPECT_EQ(288, format->height);
-  EXPECT_EQ(5, format->framerate());
+  EXPECT_EQ(30, format->framerate());
 
   EXPECT_EQ(rtc::Optional<bool>(false), source_->needs_denoising());
 }
@@ -492,5 +492,5 @@
                  kMaxWaitMs);
   const cricket::VideoFormat* format = capturer_->GetCaptureFormat();
   ASSERT_TRUE(format != NULL);
-  EXPECT_EQ(1, format->framerate());
+  EXPECT_EQ(30, format->framerate());
 }
diff --git a/webrtc/call/bitrate_estimator_tests.cc b/webrtc/call/bitrate_estimator_tests.cc
index 78c2774..46f29da 100644
--- a/webrtc/call/bitrate_estimator_tests.cc
+++ b/webrtc/call/bitrate_estimator_tests.cc
@@ -127,7 +127,7 @@
     video_send_config_.encoder_settings.payload_name = "FAKE";
     video_send_config_.encoder_settings.payload_type =
         kFakeVideoSendPayloadType;
-    test::FillEncoderConfiguration(1, &video_encoder_config_);
+    video_encoder_config_.streams = test::CreateVideoStreams(1);
 
     receive_config_ = VideoReceiveStream::Config(receive_transport_.get());
     // receive_config_.decoders will be set by every stream separately.
@@ -175,9 +175,10 @@
       send_stream_ = test_->sender_call_->CreateVideoSendStream(
           test_->video_send_config_.Copy(),
           test_->video_encoder_config_.Copy());
-      RTC_DCHECK_EQ(1u, test_->video_encoder_config_.number_of_streams);
+      RTC_DCHECK_EQ(1u, test_->video_encoder_config_.streams.size());
       frame_generator_capturer_.reset(test::FrameGeneratorCapturer::Create(
-          kDefaultWidth, kDefaultHeight, kDefaultFramerate,
+          test_->video_encoder_config_.streams[0].width,
+          test_->video_encoder_config_.streams[0].height, 30,
           Clock::GetRealTimeClock()));
       send_stream_->SetSource(frame_generator_capturer_.get());
       send_stream_->Start();
diff --git a/webrtc/call/call_perf_tests.cc b/webrtc/call/call_perf_tests.cc
index 05d893c..6258a85 100644
--- a/webrtc/call/call_perf_tests.cc
+++ b/webrtc/call/call_perf_tests.cc
@@ -264,9 +264,7 @@
   EXPECT_EQ(1u, video_receive_streams_.size());
   observer.set_receive_stream(video_receive_streams_[0]);
   DriftingClock drifting_clock(clock_, video_ntp_speed);
-  CreateFrameGeneratorCapturerWithDrift(&drifting_clock, video_rtp_speed,
-                                        kDefaultFramerate, kDefaultWidth,
-                                        kDefaultHeight);
+  CreateFrameGeneratorCapturerWithDrift(&drifting_clock, video_rtp_speed);
 
   Start();
 
@@ -620,24 +618,6 @@
   static const uint32_t kReconfigureThresholdKbps = 600;
   static const uint32_t kPermittedReconfiguredBitrateDiffKbps = 100;
 
-  class VideoStreamFactory
-      : public VideoEncoderConfig::VideoStreamFactoryInterface {
-   public:
-    VideoStreamFactory() {}
-
-   private:
-    std::vector<VideoStream> CreateEncoderStreams(
-        int width,
-        int height,
-        const VideoEncoderConfig& encoder_config) override {
-      std::vector<VideoStream> streams =
-          test::CreateVideoStreams(width, height, encoder_config);
-      streams[0].min_bitrate_bps = 50000;
-      streams[0].target_bitrate_bps = streams[0].max_bitrate_bps = 2000000;
-      return streams;
-    }
-  };
-
   class BitrateObserver : public test::EndToEndTest, public test::FakeEncoder {
    public:
     BitrateObserver()
@@ -651,18 +631,12 @@
     int32_t InitEncode(const VideoCodec* config,
                        int32_t number_of_cores,
                        size_t max_payload_size) override {
-      ++encoder_inits_;
-      if (encoder_inits_ == 1) {
-        // First time initialization. Frame size is not known.
+      if (encoder_inits_ == 0) {
         EXPECT_EQ(kInitialBitrateKbps, config->startBitrate)
             << "Encoder not initialized at expected bitrate.";
-      } else if (encoder_inits_ == 2) {
-        // First time initialization. Frame size is known.
-        EXPECT_EQ(kDefaultWidth, config->width);
-        EXPECT_EQ(kDefaultHeight, config->height);
-      } else if (encoder_inits_ == 3) {
-        EXPECT_EQ(2 * kDefaultWidth, config->width);
-        EXPECT_EQ(2 * kDefaultHeight, config->height);
+      }
+      ++encoder_inits_;
+      if (encoder_inits_ == 2) {
         EXPECT_GE(last_set_bitrate_, kReconfigureThresholdKbps);
         EXPECT_NEAR(config->startBitrate,
                     last_set_bitrate_,
@@ -676,7 +650,7 @@
     int32_t SetRates(uint32_t new_target_bitrate_kbps,
                      uint32_t framerate) override {
       last_set_bitrate_ = new_target_bitrate_kbps;
-      if (encoder_inits_ == 2 &&
+      if (encoder_inits_ == 1 &&
           new_target_bitrate_kbps > kReconfigureThresholdKbps) {
         time_to_reconfigure_.Set();
       }
@@ -694,8 +668,9 @@
         std::vector<VideoReceiveStream::Config>* receive_configs,
         VideoEncoderConfig* encoder_config) override {
       send_config->encoder_settings.encoder = this;
-      encoder_config->video_stream_factory =
-          new rtc::RefCountedObject<VideoStreamFactory>();
+      encoder_config->streams[0].min_bitrate_bps = 50000;
+      encoder_config->streams[0].target_bitrate_bps =
+          encoder_config->streams[0].max_bitrate_bps = 2000000;
 
       encoder_config_ = encoder_config->Copy();
     }
@@ -706,15 +681,11 @@
       send_stream_ = send_stream;
     }
 
-    void OnFrameGeneratorCapturerCreated(
-        test::FrameGeneratorCapturer* frame_generator_capturer) override {
-      frame_generator_ = frame_generator_capturer;
-    }
-
     void PerformTest() override {
       ASSERT_TRUE(time_to_reconfigure_.Wait(kDefaultTimeoutMs))
           << "Timed out before receiving an initial high bitrate.";
-      frame_generator_->ChangeResolution(kDefaultWidth * 2, kDefaultHeight * 2);
+      encoder_config_.streams[0].width *= 2;
+      encoder_config_.streams[0].height *= 2;
       send_stream_->ReconfigureVideoEncoder(encoder_config_.Copy());
       EXPECT_TRUE(Wait())
           << "Timed out while waiting for a couple of high bitrate estimates "
@@ -726,7 +697,6 @@
     int encoder_inits_;
     uint32_t last_set_bitrate_;
     VideoSendStream* send_stream_;
-    test::FrameGeneratorCapturer* frame_generator_;
     VideoEncoderConfig encoder_config_;
   } test;
 
diff --git a/webrtc/call/rampup_tests.cc b/webrtc/call/rampup_tests.cc
index b9a4564..bbfd87b 100644
--- a/webrtc/call/rampup_tests.cc
+++ b/webrtc/call/rampup_tests.cc
@@ -13,7 +13,6 @@
 #include "webrtc/test/gtest.h"
 #include "webrtc/base/checks.h"
 #include "webrtc/base/platform_thread.h"
-#include "webrtc/test/encoder_settings.h"
 #include "webrtc/test/testsupport/perf_test.h"
 
 namespace webrtc {
@@ -97,47 +96,24 @@
   return num_audio_streams_;
 }
 
-class RampUpTester::VideoStreamFactory
-    : public VideoEncoderConfig::VideoStreamFactoryInterface {
- public:
-  VideoStreamFactory() {}
-
- private:
-  std::vector<VideoStream> CreateEncoderStreams(
-      int width,
-      int height,
-      const VideoEncoderConfig& encoder_config) override {
-    std::vector<VideoStream> streams =
-        test::CreateVideoStreams(width, height, encoder_config);
-    if (encoder_config.number_of_streams == 1) {
-      streams[0].target_bitrate_bps = streams[0].max_bitrate_bps = 2000000;
-    }
-    return streams;
-  }
-};
-
 void RampUpTester::ModifyVideoConfigs(
     VideoSendStream::Config* send_config,
     std::vector<VideoReceiveStream::Config>* receive_configs,
     VideoEncoderConfig* encoder_config) {
   send_config->suspend_below_min_bitrate = true;
-  encoder_config->number_of_streams = num_video_streams_;
-  encoder_config->max_bitrate_bps = 2000000;
-  encoder_config->video_stream_factory =
-      new rtc::RefCountedObject<RampUpTester::VideoStreamFactory>();
+
   if (num_video_streams_ == 1) {
+    encoder_config->streams[0].target_bitrate_bps =
+        encoder_config->streams[0].max_bitrate_bps = 2000000;
     // For single stream rampup until 1mbps
     expected_bitrate_bps_ = kSingleStreamTargetBps;
   } else {
     // For multi stream rampup until all streams are being sent. That means
-    // enough bitrate to send all the target streams plus the min bitrate of
+    // enough birate to send all the target streams plus the min bitrate of
     // the last one.
-    std::vector<VideoStream> streams = test::CreateVideoStreams(
-        test::CallTest::kDefaultWidth, test::CallTest::kDefaultHeight,
-        *encoder_config);
-    expected_bitrate_bps_ = streams.back().min_bitrate_bps;
-    for (size_t i = 0; i < streams.size() - 1; ++i) {
-      expected_bitrate_bps_ += streams[i].target_bitrate_bps;
+    expected_bitrate_bps_ = encoder_config->streams.back().min_bitrate_bps;
+    for (size_t i = 0; i < encoder_config->streams.size() - 1; ++i) {
+      expected_bitrate_bps_ += encoder_config->streams[i].target_bitrate_bps;
     }
   }
 
diff --git a/webrtc/call/rampup_tests.h b/webrtc/call/rampup_tests.h
index f3779e2..efc56ad 100644
--- a/webrtc/call/rampup_tests.h
+++ b/webrtc/call/rampup_tests.h
@@ -70,7 +70,6 @@
 
  private:
   typedef std::map<uint32_t, uint32_t> SsrcMap;
-  class VideoStreamFactory;
 
   Call::Config GetSenderCallConfig() override;
   void OnVideoStreamsCreated(
diff --git a/webrtc/config.cc b/webrtc/config.cc
index 7c1a0a8..3761d66 100644
--- a/webrtc/config.cc
+++ b/webrtc/config.cc
@@ -117,14 +117,21 @@
     : content_type(ContentType::kRealtimeVideo),
       encoder_specific_settings(nullptr),
       min_transmit_bitrate_bps(0),
-      max_bitrate_bps(0),
-      number_of_streams(0) {}
+      expect_encode_from_texture(false) {}
 
 VideoEncoderConfig::~VideoEncoderConfig() = default;
 
 std::string VideoEncoderConfig::ToString() const {
   std::stringstream ss;
-  ss << "{content_type: ";
+
+  ss << "{streams: [";
+  for (size_t i = 0; i < streams.size(); ++i) {
+    ss << streams[i].ToString();
+    if (i != streams.size() - 1)
+      ss << ", ";
+  }
+  ss << ']';
+  ss << ", content_type: ";
   switch (content_type) {
     case ContentType::kRealtimeVideo:
       ss << "kRealtimeVideo";
diff --git a/webrtc/config.h b/webrtc/config.h
index 0231cb5..0e8b769 100644
--- a/webrtc/config.h
+++ b/webrtc/config.h
@@ -125,7 +125,7 @@
   std::vector<int> temporal_layer_thresholds_bps;
 };
 
-class VideoEncoderConfig {
+struct VideoEncoderConfig {
  public:
   // These are reference counted to permit copying VideoEncoderConfig and be
   // kept alive until all encoder_specific_settings go out of scope.
@@ -143,13 +143,14 @@
     virtual void FillVideoCodecH264(VideoCodecH264* h264_settings) const;
    private:
     virtual ~EncoderSpecificSettings() {}
-    friend class VideoEncoderConfig;
+    friend struct VideoEncoderConfig;
   };
 
   class H264EncoderSpecificSettings : public EncoderSpecificSettings {
    public:
     explicit H264EncoderSpecificSettings(const VideoCodecH264& specifics);
-    void FillVideoCodecH264(VideoCodecH264* h264_settings) const override;
+    virtual void FillVideoCodecH264(
+        VideoCodecH264* h264_settings) const override;
 
    private:
     VideoCodecH264 specifics_;
@@ -158,7 +159,7 @@
   class Vp8EncoderSpecificSettings : public EncoderSpecificSettings {
    public:
     explicit Vp8EncoderSpecificSettings(const VideoCodecVP8& specifics);
-    void FillVideoCodecVp8(VideoCodecVP8* vp8_settings) const override;
+    virtual void FillVideoCodecVp8(VideoCodecVP8* vp8_settings) const override;
 
    private:
     VideoCodecVP8 specifics_;
@@ -167,7 +168,7 @@
   class Vp9EncoderSpecificSettings : public EncoderSpecificSettings {
    public:
     explicit Vp9EncoderSpecificSettings(const VideoCodecVP9& specifics);
-    void FillVideoCodecVp9(VideoCodecVP9* vp9_settings) const override;
+    virtual void FillVideoCodecVp9(VideoCodecVP9* vp9_settings) const override;
 
    private:
     VideoCodecVP9 specifics_;
@@ -178,21 +179,6 @@
     kScreen,
   };
 
-  class VideoStreamFactoryInterface : public rtc::RefCountInterface {
-   public:
-    // An implementation should return a std::vector<VideoStream> with the
-    // wanted VideoStream settings for the given video resolution.
-    // The size of the vector may not be larger than
-    // |encoder_config.number_of_streams|.
-    virtual std::vector<VideoStream> CreateEncoderStreams(
-        int width,
-        int height,
-        const VideoEncoderConfig& encoder_config) = 0;
-
-   protected:
-    virtual ~VideoStreamFactoryInterface() {}
-  };
-
   VideoEncoderConfig& operator=(VideoEncoderConfig&&) = default;
   VideoEncoderConfig& operator=(const VideoEncoderConfig&) = delete;
 
@@ -204,7 +190,7 @@
   ~VideoEncoderConfig();
   std::string ToString() const;
 
-  rtc::scoped_refptr<VideoStreamFactoryInterface> video_stream_factory;
+  std::vector<VideoStream> streams;
   std::vector<SpatialLayer> spatial_layers;
   ContentType content_type;
   rtc::scoped_refptr<const EncoderSpecificSettings> encoder_specific_settings;
@@ -214,10 +200,7 @@
   // maintaining a higher bitrate estimate. Padding will however not be sent
   // unless the estimated bandwidth indicates that the link can handle it.
   int min_transmit_bitrate_bps;
-  int max_bitrate_bps;
-
-  // Max number of encoded VideoStreams to produce.
-  size_t number_of_streams;
+  bool expect_encode_from_texture;
 
  private:
   // Access to the copy constructor is private to force use of the Copy()
diff --git a/webrtc/media/base/fakevideocapturer.h b/webrtc/media/base/fakevideocapturer.h
index ff786f2..8ba56f1 100644
--- a/webrtc/media/base/fakevideocapturer.h
+++ b/webrtc/media/base/fakevideocapturer.h
@@ -29,7 +29,7 @@
 // Fake video capturer that allows the test to manually pump in frames.
 class FakeVideoCapturer : public cricket::VideoCapturer {
  public:
-  explicit FakeVideoCapturer(bool is_screencast)
+  FakeVideoCapturer(bool is_screencast)
       : running_(false),
         initial_timestamp_(rtc::TimeNanos()),
         next_timestamp_(rtc::kNumNanosecsPerMillisec),
@@ -124,7 +124,10 @@
   sigslot::signal1<FakeVideoCapturer*> SignalDestroyed;
 
   cricket::CaptureState Start(const cricket::VideoFormat& format) override {
-    SetCaptureFormat(&format);
+    cricket::VideoFormat supported;
+    if (GetBestCaptureFormat(format, &supported)) {
+      SetCaptureFormat(&supported);
+    }
     running_ = true;
     SetCaptureState(cricket::CS_RUNNING);
     return cricket::CS_RUNNING;
diff --git a/webrtc/media/engine/constants.h b/webrtc/media/engine/constants.h
index 19d06a1..68a2bc6 100644
--- a/webrtc/media/engine/constants.h
+++ b/webrtc/media/engine/constants.h
@@ -18,7 +18,9 @@
 
 extern const char kH264CodecName[];
 
-extern const int kMinVideoBitrateKbps;
+extern const int kMinVideoBitrate;
+extern const int kStartVideoBitrate;
+extern const int kMaxVideoBitrate;
 
 }  // namespace cricket
 
diff --git a/webrtc/media/engine/fakewebrtccall.cc b/webrtc/media/engine/fakewebrtccall.cc
index 88f9927..9515505 100644
--- a/webrtc/media/engine/fakewebrtccall.cc
+++ b/webrtc/media/engine/fakewebrtccall.cc
@@ -124,9 +124,8 @@
   return encoder_config_;
 }
 
-const std::vector<webrtc::VideoStream>& FakeVideoSendStream::GetVideoStreams()
-    const {
-  return video_streams_;
+std::vector<webrtc::VideoStream> FakeVideoSendStream::GetVideoStreams() {
+  return encoder_config_.streams;
 }
 
 bool FakeVideoSendStream::IsSending() const {
@@ -172,12 +171,6 @@
 
 void FakeVideoSendStream::OnFrame(const webrtc::VideoFrame& frame) {
   ++num_swapped_frames_;
-  if (frame.width() != last_frame_.width() ||
-      frame.height() != last_frame_.height() ||
-      frame.rotation() != last_frame_.rotation()) {
-    video_streams_ = encoder_config_.video_stream_factory->CreateEncoderStreams(
-        frame.width(), frame.height(), encoder_config_);
-  }
   last_frame_.ShallowCopy(frame);
 }
 
@@ -199,20 +192,18 @@
 
 void FakeVideoSendStream::ReconfigureVideoEncoder(
     webrtc::VideoEncoderConfig config) {
-  video_streams_ = config.video_stream_factory->CreateEncoderStreams(
-      last_frame_.width(), last_frame_.height(), config);
   if (config.encoder_specific_settings != NULL) {
     if (config_.encoder_settings.payload_name == "VP8") {
       config.encoder_specific_settings->FillVideoCodecVp8(&vpx_settings_.vp8);
-      if (!video_streams_.empty()) {
+      if (!config.streams.empty()) {
         vpx_settings_.vp8.numberOfTemporalLayers = static_cast<unsigned char>(
-            video_streams_.back().temporal_layer_thresholds_bps.size() + 1);
+            config.streams.back().temporal_layer_thresholds_bps.size() + 1);
       }
     } else if (config_.encoder_settings.payload_name == "VP9") {
       config.encoder_specific_settings->FillVideoCodecVp9(&vpx_settings_.vp9);
-      if (!video_streams_.empty()) {
+      if (!config.streams.empty()) {
         vpx_settings_.vp9.numberOfTemporalLayers = static_cast<unsigned char>(
-            video_streams_.back().temporal_layer_thresholds_bps.size() + 1);
+            config.streams.back().temporal_layer_thresholds_bps.size() + 1);
       }
     } else {
       ADD_FAILURE() << "Unsupported encoder payload: "
diff --git a/webrtc/media/engine/fakewebrtccall.h b/webrtc/media/engine/fakewebrtccall.h
index 5719070..170e6fc 100644
--- a/webrtc/media/engine/fakewebrtccall.h
+++ b/webrtc/media/engine/fakewebrtccall.h
@@ -109,7 +109,7 @@
   ~FakeVideoSendStream() override;
   const webrtc::VideoSendStream::Config& GetConfig() const;
   const webrtc::VideoEncoderConfig& GetEncoderConfig() const;
-  const std::vector<webrtc::VideoStream>& GetVideoStreams() const;
+  std::vector<webrtc::VideoStream> GetVideoStreams();
 
   bool IsSending() const;
   bool GetVp8Settings(webrtc::VideoCodecVP8* settings) const;
@@ -142,7 +142,6 @@
   bool sending_;
   webrtc::VideoSendStream::Config config_;
   webrtc::VideoEncoderConfig encoder_config_;
-  std::vector<webrtc::VideoStream> video_streams_;
   bool codec_settings_set_;
   union VpxSettings {
     webrtc::VideoCodecVP8 vp8;
diff --git a/webrtc/media/engine/webrtcvideoengine2.cc b/webrtc/media/engine/webrtcvideoengine2.cc
index 3a3961c..5176c11 100644
--- a/webrtc/media/engine/webrtcvideoengine2.cc
+++ b/webrtc/media/engine/webrtcvideoengine2.cc
@@ -14,7 +14,6 @@
 #include <algorithm>
 #include <set>
 #include <string>
-#include <utility>
 
 #include "webrtc/base/copyonwritebuffer.h"
 #include "webrtc/base/logging.h"
@@ -323,83 +322,12 @@
   }
   return 1;
 }
-
-class EncoderStreamFactory
-    : public webrtc::VideoEncoderConfig::VideoStreamFactoryInterface {
- public:
-  EncoderStreamFactory(std::string codec_name,
-                       int max_qp,
-                       int max_framerate,
-                       bool is_screencast,
-                       bool conference_mode)
-      : codec_name_(codec_name),
-        max_qp_(max_qp),
-        max_framerate_(max_framerate),
-        is_screencast_(is_screencast),
-        conference_mode_(conference_mode) {}
-
- private:
-  std::vector<webrtc::VideoStream> CreateEncoderStreams(
-      int width,
-      int height,
-      const webrtc::VideoEncoderConfig& encoder_config) override {
-    RTC_DCHECK(encoder_config.number_of_streams > 1 ? !is_screencast_ : true);
-    if (encoder_config.number_of_streams > 1) {
-      return GetSimulcastConfig(encoder_config.number_of_streams, width, height,
-                                encoder_config.max_bitrate_bps, max_qp_,
-                                max_framerate_);
-    }
-
-    // For unset max bitrates set default bitrate for non-simulcast.
-    int max_bitrate_bps =
-        (encoder_config.max_bitrate_bps > 0)
-            ? encoder_config.max_bitrate_bps
-            : GetMaxDefaultVideoBitrateKbps(width, height) * 1000;
-
-    webrtc::VideoStream stream;
-    stream.width = width;
-    stream.height = height;
-    stream.max_framerate = max_framerate_;
-    stream.min_bitrate_bps = kMinVideoBitrateKbps * 1000;
-    stream.target_bitrate_bps = stream.max_bitrate_bps = max_bitrate_bps;
-    stream.max_qp = max_qp_;
-
-    // Conference mode screencast uses 2 temporal layers split at 100kbit.
-    if (conference_mode_ && is_screencast_) {
-      ScreenshareLayerConfig config = ScreenshareLayerConfig::GetDefault();
-      // For screenshare in conference mode, tl0 and tl1 bitrates are
-      // piggybacked
-      // on the VideoCodec struct as target and max bitrates, respectively.
-      // See eg. webrtc::VP8EncoderImpl::SetRates().
-      stream.target_bitrate_bps = config.tl0_bitrate_kbps * 1000;
-      stream.max_bitrate_bps = config.tl1_bitrate_kbps * 1000;
-      stream.temporal_layer_thresholds_bps.clear();
-      stream.temporal_layer_thresholds_bps.push_back(config.tl0_bitrate_kbps *
-                                                     1000);
-    }
-
-    if (CodecNamesEq(codec_name_, kVp9CodecName) && !is_screencast_) {
-      stream.temporal_layer_thresholds_bps.resize(
-          GetDefaultVp9TemporalLayers() - 1);
-    }
-
-    std::vector<webrtc::VideoStream> streams;
-    streams.push_back(stream);
-    return streams;
-  }
-
-  const std::string codec_name_;
-  const int max_qp_;
-  const int max_framerate_;
-  const bool is_screencast_;
-  const bool conference_mode_;
-};
-
 }  // namespace
 
 // Constants defined in webrtc/media/engine/constants.h
 // TODO(pbos): Move these to a separate constants.cc file.
-const int kMinVideoBitrateKbps = 30;
+const int kMinVideoBitrate = 30;
+const int kStartVideoBitrate = 300;
 
 const int kVideoMtu = 1200;
 const int kVideoRtpBufferSize = 65536;
@@ -470,10 +398,61 @@
   return codecs;
 }
 
+std::vector<webrtc::VideoStream>
+WebRtcVideoChannel2::WebRtcVideoSendStream::CreateSimulcastVideoStreams(
+    const VideoCodec& codec,
+    const VideoOptions& options,
+    int max_bitrate_bps,
+    size_t num_streams) {
+  int max_qp = kDefaultQpMax;
+  codec.GetParam(kCodecParamMaxQuantization, &max_qp);
+
+  return GetSimulcastConfig(
+      num_streams, codec.width, codec.height, max_bitrate_bps, max_qp,
+      codec.framerate != 0 ? codec.framerate : kDefaultVideoMaxFramerate);
+}
+
+std::vector<webrtc::VideoStream>
+WebRtcVideoChannel2::WebRtcVideoSendStream::CreateVideoStreams(
+    const VideoCodec& codec,
+    const VideoOptions& options,
+    int max_bitrate_bps,
+    size_t num_streams) {
+  int codec_max_bitrate_kbps;
+  if (codec.GetParam(kCodecParamMaxBitrate, &codec_max_bitrate_kbps)) {
+    max_bitrate_bps = codec_max_bitrate_kbps * 1000;
+  }
+  if (num_streams != 1) {
+    return CreateSimulcastVideoStreams(codec, options, max_bitrate_bps,
+                                       num_streams);
+  }
+
+  // For unset max bitrates set default bitrate for non-simulcast.
+  if (max_bitrate_bps <= 0) {
+    max_bitrate_bps =
+        GetMaxDefaultVideoBitrateKbps(codec.width, codec.height) * 1000;
+  }
+
+  webrtc::VideoStream stream;
+  stream.width = codec.width;
+  stream.height = codec.height;
+  stream.max_framerate =
+      codec.framerate != 0 ? codec.framerate : kDefaultVideoMaxFramerate;
+
+  stream.min_bitrate_bps = kMinVideoBitrate * 1000;
+  stream.target_bitrate_bps = stream.max_bitrate_bps = max_bitrate_bps;
+
+  int max_qp = kDefaultQpMax;
+  codec.GetParam(kCodecParamMaxQuantization, &max_qp);
+  stream.max_qp = max_qp;
+  std::vector<webrtc::VideoStream> streams;
+  streams.push_back(stream);
+  return streams;
+}
+
 rtc::scoped_refptr<webrtc::VideoEncoderConfig::EncoderSpecificSettings>
 WebRtcVideoChannel2::WebRtcVideoSendStream::ConfigureVideoEncoderSettings(
     const VideoCodec& codec) {
-  RTC_DCHECK_RUN_ON(&thread_checker_);
   bool is_screencast = parameters_.options.is_screencast.value_or(false);
   // No automatic resizing when using simulcast or screencast.
   bool automatic_resize =
@@ -1564,7 +1543,6 @@
     : config(std::move(config)),
       options(options),
       max_bitrate_bps(max_bitrate_bps),
-      conference_mode(false),
       codec_settings(codec_settings) {}
 
 WebRtcVideoChannel2::WebRtcVideoSendStream::AllocatedEncoder::AllocatedEncoder(
@@ -1609,6 +1587,7 @@
       encoder_sink_(nullptr),
       parameters_(std::move(config), options, max_bitrate_bps, codec_settings),
       rtp_parameters_(CreateRtpParametersWithOneEncoding()),
+      pending_encoder_reconfiguration_(false),
       allocated_encoder_(nullptr, webrtc::kVideoCodecUnknown, false),
       sending_(false),
       last_frame_timestamp_us_(0) {
@@ -1676,6 +1655,7 @@
     last_frame_info_.height = video_frame.height();
     last_frame_info_.rotation = video_frame.rotation();
     last_frame_info_.is_texture = video_frame.is_texture();
+    pending_encoder_reconfiguration_ = true;
 
     LOG(LS_INFO) << "Video frame parameters changed: dimensions="
                  << last_frame_info_.width << "x" << last_frame_info_.height
@@ -1690,13 +1670,22 @@
 
   last_frame_timestamp_us_ = video_frame.timestamp_us();
 
+  if (pending_encoder_reconfiguration_) {
+    ReconfigureEncoder();
+    pending_encoder_reconfiguration_ = false;
+  }
+
+  // Not sending, abort after reconfiguration. Reconfiguration should still
+  // occur to permit sending this input as quickly as possible once we start
+  // sending (without having to reconfigure then).
+  if (!sending_) {
+    return;
+  }
+
   ++frame_count_;
   if (cpu_restricted_counter_ > 0)
     ++cpu_restricted_frame_count_;
 
-  // Forward frame to the encoder regardless if we are sending or not. This is
-  // to ensure that the encoder can be reconfigured with the correct frame size
-  // as quickly as possible.
   encoder_sink_->OnFrame(video_frame);
 }
 
@@ -1705,7 +1694,7 @@
     const VideoOptions* options,
     rtc::VideoSourceInterface<cricket::VideoFrame>* source) {
   TRACE_EVENT0("webrtc", "WebRtcVideoSendStream::SetVideoSend");
-  RTC_DCHECK_RUN_ON(&thread_checker_);
+  RTC_DCHECK(thread_checker_.CalledOnValidThread());
 
   // Ignore |options| pointer if |enable| is false.
   bool options_present = enable && options;
@@ -1714,47 +1703,50 @@
     DisconnectSource();
   }
 
-  if (options_present) {
-    VideoOptions old_options = parameters_.options;
-    parameters_.options.SetAll(*options);
-    // If options has changed and SetCodec has been called.
-    if (parameters_.options != old_options && stream_) {
-      ReconfigureEncoder();
-    }
-  }
-
-  if (source_changing) {
+  if (options_present || source_changing) {
     rtc::CritScope cs(&lock_);
-    if (source == nullptr && encoder_sink_ != nullptr &&
-        last_frame_info_.width > 0) {
-      LOG(LS_VERBOSE) << "Disabling capturer, sending black frame.";
-      // Force this black frame not to be dropped due to timestamp order
-      // check. As IncomingCapturedFrame will drop the frame if this frame's
-      // timestamp is less than or equal to last frame's timestamp, it is
-      // necessary to give this black frame a larger timestamp than the
-      // previous one.
-      last_frame_timestamp_us_ += rtc::kNumMicrosecsPerMillisec;
-      rtc::scoped_refptr<webrtc::I420Buffer> black_buffer(
-          webrtc::I420Buffer::Create(last_frame_info_.width,
-                                     last_frame_info_.height));
-      black_buffer->SetToBlack();
 
-      encoder_sink_->OnFrame(webrtc::VideoFrame(
-          black_buffer, last_frame_info_.rotation, last_frame_timestamp_us_));
+    if (options_present) {
+      VideoOptions old_options = parameters_.options;
+      parameters_.options.SetAll(*options);
+      // Reconfigure encoder settings on the next frame or stream
+      // recreation if the options changed.
+      if (parameters_.options != old_options) {
+        pending_encoder_reconfiguration_ = true;
+      }
     }
-    source_ = source;
+
+    if (source_changing) {
+      if (source == nullptr && encoder_sink_ != nullptr) {
+        LOG(LS_VERBOSE) << "Disabling capturer, sending black frame.";
+        // Force this black frame not to be dropped due to timestamp order
+        // check. As IncomingCapturedFrame will drop the frame if this frame's
+        // timestamp is less than or equal to last frame's timestamp, it is
+        // necessary to give this black frame a larger timestamp than the
+        // previous one.
+        last_frame_timestamp_us_ += rtc::kNumMicrosecsPerMillisec;
+        rtc::scoped_refptr<webrtc::I420Buffer> black_buffer(
+            webrtc::I420Buffer::Create(last_frame_info_.width,
+                                       last_frame_info_.height));
+        black_buffer->SetToBlack();
+
+        encoder_sink_->OnFrame(webrtc::VideoFrame(
+            black_buffer, last_frame_info_.rotation, last_frame_timestamp_us_));
+      }
+      source_ = source;
+    }
   }
 
+  // |source_->AddOrUpdateSink| may not be called while holding |lock_| since
+  // that might cause a lock order inversion.
   if (source_changing && source_) {
-    // |source_->AddOrUpdateSink| may not be called while holding |lock_| since
-    // that might cause a lock order inversion.
     source_->AddOrUpdateSink(this, sink_wants_);
   }
   return true;
 }
 
 void WebRtcVideoChannel2::WebRtcVideoSendStream::DisconnectSource() {
-  RTC_DCHECK_RUN_ON(&thread_checker_);
+  RTC_DCHECK(thread_checker_.CalledOnValidThread());
   if (source_ == nullptr) {
     return;
   }
@@ -1789,7 +1781,6 @@
 WebRtcVideoChannel2::WebRtcVideoSendStream::AllocatedEncoder
 WebRtcVideoChannel2::WebRtcVideoSendStream::CreateVideoEncoder(
     const VideoCodec& codec) {
-  RTC_DCHECK_RUN_ON(&thread_checker_);
   webrtc::VideoCodecType type = CodecTypeFromName(codec.name);
 
   // Do not re-create encoders of the same type.
@@ -1824,7 +1815,6 @@
 
 void WebRtcVideoChannel2::WebRtcVideoSendStream::DestroyVideoEncoder(
     AllocatedEncoder* encoder) {
-  RTC_DCHECK_RUN_ON(&thread_checker_);
   if (encoder->external) {
     external_encoder_factory_->DestroyVideoEncoder(encoder->external_encoder);
   }
@@ -1833,9 +1823,8 @@
 
 void WebRtcVideoChannel2::WebRtcVideoSendStream::SetCodec(
     const VideoCodecSettings& codec_settings) {
-  RTC_DCHECK_RUN_ON(&thread_checker_);
   parameters_.encoder_config = CreateVideoEncoderConfig(codec_settings.codec);
-  RTC_DCHECK_GT(parameters_.encoder_config.number_of_streams, 0u);
+  RTC_DCHECK(!parameters_.encoder_config.streams.empty());
 
   AllocatedEncoder new_encoder = CreateVideoEncoder(codec_settings.codec);
   parameters_.config.encoder_settings.encoder = new_encoder.encoder;
@@ -1876,38 +1865,41 @@
 
 void WebRtcVideoChannel2::WebRtcVideoSendStream::SetSendParameters(
     const ChangedSendParameters& params) {
-  RTC_DCHECK_RUN_ON(&thread_checker_);
-  // |recreate_stream| means construction-time parameters have changed and the
-  // sending stream needs to be reset with the new config.
-  bool recreate_stream = false;
-  if (params.rtcp_mode) {
-    parameters_.config.rtp.rtcp_mode = *params.rtcp_mode;
-    recreate_stream = true;
-  }
-  if (params.rtp_header_extensions) {
-    parameters_.config.rtp.extensions = *params.rtp_header_extensions;
-    recreate_stream = true;
-  }
-  if (params.max_bandwidth_bps) {
-    parameters_.max_bitrate_bps = *params.max_bandwidth_bps;
-    ReconfigureEncoder();
-  }
-  if (params.conference_mode) {
-    parameters_.conference_mode = *params.conference_mode;
-  }
+  {
+    rtc::CritScope cs(&lock_);
+    // |recreate_stream| means construction-time parameters have changed and the
+    // sending stream needs to be reset with the new config.
+    bool recreate_stream = false;
+    if (params.rtcp_mode) {
+      parameters_.config.rtp.rtcp_mode = *params.rtcp_mode;
+      recreate_stream = true;
+    }
+    if (params.rtp_header_extensions) {
+      parameters_.config.rtp.extensions = *params.rtp_header_extensions;
+      recreate_stream = true;
+    }
+    if (params.max_bandwidth_bps) {
+      parameters_.max_bitrate_bps = *params.max_bandwidth_bps;
+      pending_encoder_reconfiguration_ = true;
+    }
+    if (params.conference_mode) {
+      parameters_.conference_mode = *params.conference_mode;
+    }
 
-  // Set codecs and options.
-  if (params.codec) {
-    SetCodec(*params.codec);
-    recreate_stream = false;  // SetCodec has already recreated the stream.
-  } else if (params.conference_mode && parameters_.codec_settings) {
-    SetCodec(*parameters_.codec_settings);
-    recreate_stream = false;  // SetCodec has already recreated the stream.
-  }
-  if (recreate_stream) {
-    LOG(LS_INFO) << "RecreateWebRtcStream (send) because of SetSendParameters";
-    RecreateWebRtcStream();
-  }
+    // Set codecs and options.
+    if (params.codec) {
+      SetCodec(*params.codec);
+      recreate_stream = false;  // SetCodec has already recreated the stream.
+    } else if (params.conference_mode && parameters_.codec_settings) {
+      SetCodec(*parameters_.codec_settings);
+      recreate_stream = false;  // SetCodec has already recreated the stream.
+    }
+    if (recreate_stream) {
+      LOG(LS_INFO)
+          << "RecreateWebRtcStream (send) because of SetSendParameters";
+      RecreateWebRtcStream();
+    }
+  }  // release |lock_|
 
   // |source_->AddOrUpdateSink| may not be called while holding |lock_| since
   // that might cause a lock order inversion.
@@ -1922,19 +1914,18 @@
 
 bool WebRtcVideoChannel2::WebRtcVideoSendStream::SetRtpParameters(
     const webrtc::RtpParameters& new_parameters) {
-  RTC_DCHECK_RUN_ON(&thread_checker_);
   if (!ValidateRtpParameters(new_parameters)) {
     return false;
   }
 
-  bool reconfigure_encoder = new_parameters.encodings[0].max_bitrate_bps !=
-                             rtp_parameters_.encodings[0].max_bitrate_bps;
+  rtc::CritScope cs(&lock_);
+  if (new_parameters.encodings[0].max_bitrate_bps !=
+      rtp_parameters_.encodings[0].max_bitrate_bps) {
+    pending_encoder_reconfiguration_ = true;
+  }
   rtp_parameters_ = new_parameters;
   // Codecs are currently handled at the WebRtcVideoChannel2 level.
   rtp_parameters_.codecs.clear();
-  if (reconfigure_encoder) {
-    ReconfigureEncoder();
-  }
   // Encoding may have been activated/deactivated.
   UpdateSendState();
   return true;
@@ -1942,7 +1933,7 @@
 
 webrtc::RtpParameters
 WebRtcVideoChannel2::WebRtcVideoSendStream::GetRtpParameters() const {
-  RTC_DCHECK_RUN_ON(&thread_checker_);
+  rtc::CritScope cs(&lock_);
   return rtp_parameters_;
 }
 
@@ -1957,7 +1948,6 @@
 }
 
 void WebRtcVideoChannel2::WebRtcVideoSendStream::UpdateSendState() {
-  RTC_DCHECK_RUN_ON(&thread_checker_);
   // TODO(deadbeef): Need to handle more than one encoding in the future.
   RTC_DCHECK(rtp_parameters_.encodings.size() == 1u);
   if (sending_ && rtp_parameters_.encodings[0].active) {
@@ -1973,7 +1963,6 @@
 webrtc::VideoEncoderConfig
 WebRtcVideoChannel2::WebRtcVideoSendStream::CreateVideoEncoderConfig(
     const VideoCodec& codec) const {
-  RTC_DCHECK_RUN_ON(&thread_checker_);
   webrtc::VideoEncoderConfig encoder_config;
   bool is_screencast = parameters_.options.is_screencast.value_or(false);
   if (is_screencast) {
@@ -1987,39 +1976,60 @@
         webrtc::VideoEncoderConfig::ContentType::kRealtimeVideo;
   }
 
+  // Restrict dimensions according to codec max.
+  int width = last_frame_info_.width;
+  int height = last_frame_info_.height;
+  if (!is_screencast) {
+    if (codec.width < width)
+      width = codec.width;
+    if (codec.height < height)
+      height = codec.height;
+  }
+
+  VideoCodec clamped_codec = codec;
+  clamped_codec.width = width;
+  clamped_codec.height = height;
+
   // By default, the stream count for the codec configuration should match the
   // number of negotiated ssrcs. But if the codec is blacklisted for simulcast
   // or a screencast, only configure a single stream.
-  encoder_config.number_of_streams = parameters_.config.rtp.ssrcs.size();
+  size_t stream_count = parameters_.config.rtp.ssrcs.size();
   if (IsCodecBlacklistedForSimulcast(codec.name) || is_screencast) {
-    encoder_config.number_of_streams = 1;
+    stream_count = 1;
   }
 
   int stream_max_bitrate =
       MinPositive(rtp_parameters_.encodings[0].max_bitrate_bps,
                   parameters_.max_bitrate_bps);
+  encoder_config.streams = CreateVideoStreams(
+      clamped_codec, parameters_.options, stream_max_bitrate, stream_count);
+  encoder_config.expect_encode_from_texture = last_frame_info_.is_texture;
 
-  int codec_max_bitrate_kbps;
-  if (codec.GetParam(kCodecParamMaxBitrate, &codec_max_bitrate_kbps)) {
-    stream_max_bitrate = codec_max_bitrate_kbps * 1000;
+  // Conference mode screencast uses 2 temporal layers split at 100kbit.
+  if (parameters_.conference_mode && is_screencast &&
+      encoder_config.streams.size() == 1) {
+    ScreenshareLayerConfig config = ScreenshareLayerConfig::GetDefault();
+
+    // For screenshare in conference mode, tl0 and tl1 bitrates are piggybacked
+    // on the VideoCodec struct as target and max bitrates, respectively.
+    // See eg. webrtc::VP8EncoderImpl::SetRates().
+    encoder_config.streams[0].target_bitrate_bps =
+        config.tl0_bitrate_kbps * 1000;
+    encoder_config.streams[0].max_bitrate_bps = config.tl1_bitrate_kbps * 1000;
+    encoder_config.streams[0].temporal_layer_thresholds_bps.clear();
+    encoder_config.streams[0].temporal_layer_thresholds_bps.push_back(
+        config.tl0_bitrate_kbps * 1000);
   }
-  encoder_config.max_bitrate_bps = stream_max_bitrate;
-
-  int max_qp = kDefaultQpMax;
-  codec.GetParam(kCodecParamMaxQuantization, &max_qp);
-  int max_framerate =
-      codec.framerate != 0 ? codec.framerate : kDefaultVideoMaxFramerate;
-
-  encoder_config.video_stream_factory =
-      new rtc::RefCountedObject<EncoderStreamFactory>(
-          codec.name, max_qp, max_framerate, is_screencast,
-          parameters_.conference_mode);
+  if (CodecNamesEq(codec.name, kVp9CodecName) && !is_screencast &&
+      encoder_config.streams.size() == 1) {
+    encoder_config.streams[0].temporal_layer_thresholds_bps.resize(
+        GetDefaultVp9TemporalLayers() - 1);
+  }
   return encoder_config;
 }
 
 void WebRtcVideoChannel2::WebRtcVideoSendStream::ReconfigureEncoder() {
-  RTC_DCHECK_RUN_ON(&thread_checker_);
-  RTC_DCHECK_GT(parameters_.encoder_config.number_of_streams, 0u);
+  RTC_DCHECK(!parameters_.encoder_config.streams.empty());
 
   RTC_CHECK(parameters_.codec_settings);
   VideoCodecSettings codec_settings = *parameters_.codec_settings;
@@ -2038,7 +2048,7 @@
 }
 
 void WebRtcVideoChannel2::WebRtcVideoSendStream::SetSend(bool send) {
-  RTC_DCHECK_RUN_ON(&thread_checker_);
+  rtc::CritScope cs(&lock_);
   sending_ = send;
   UpdateSendState();
 }
@@ -2068,62 +2078,63 @@
                   this, load));
     return;
   }
-  RTC_DCHECK_RUN_ON(&thread_checker_);
+  RTC_DCHECK(thread_checker_.CalledOnValidThread());
   if (!source_) {
     return;
   }
-
-  LOG(LS_INFO) << "OnLoadUpdate " << load << ", is_screencast: "
-               << (parameters_.options.is_screencast
-                       ? (*parameters_.options.is_screencast ? "true" : "false")
-                       : "unset");
-  // Do not adapt resolution for screen content as this will likely result in
-  // blurry and unreadable text.
-  if (parameters_.options.is_screencast.value_or(false))
-    return;
-
-  rtc::Optional<int> max_pixel_count;
-  rtc::Optional<int> max_pixel_count_step_up;
-  if (load == kOveruse) {
+  {
     rtc::CritScope cs(&lock_);
-    if (cpu_restricted_counter_ >= kMaxCpuDowngrades) {
+    LOG(LS_INFO) << "OnLoadUpdate " << load << ", is_screencast: "
+                 << (parameters_.options.is_screencast
+                         ? (*parameters_.options.is_screencast ? "true"
+                                                               : "false")
+                         : "unset");
+    // Do not adapt resolution for screen content as this will likely result in
+    // blurry and unreadable text.
+    if (parameters_.options.is_screencast.value_or(false))
       return;
+
+    rtc::Optional<int> max_pixel_count;
+    rtc::Optional<int> max_pixel_count_step_up;
+    if (load == kOveruse) {
+      if (cpu_restricted_counter_ >= kMaxCpuDowngrades) {
+        return;
+      }
+      // The input video frame size will have a resolution with less than or
+      // equal to |max_pixel_count| depending on how the source can scale the
+      // input frame size.
+      max_pixel_count = rtc::Optional<int>(
+          (last_frame_info_.height * last_frame_info_.width * 3) / 5);
+      // Increase |number_of_cpu_adapt_changes_| if
+      // sink_wants_.max_pixel_count will be changed since
+      // last time |source_->AddOrUpdateSink| was called. That is, this will
+      // result in a new request for the source to change resolution.
+      if (!sink_wants_.max_pixel_count ||
+          *sink_wants_.max_pixel_count > *max_pixel_count) {
+        ++number_of_cpu_adapt_changes_;
+        ++cpu_restricted_counter_;
+      }
+    } else {
+      RTC_DCHECK(load == kUnderuse);
+      // The input video frame size will have a resolution with "one step up"
+      // pixels than |max_pixel_count_step_up| where "one step up" depends on
+      // how the source can scale the input frame size.
+      max_pixel_count_step_up =
+          rtc::Optional<int>(last_frame_info_.height * last_frame_info_.width);
+      // Increase |number_of_cpu_adapt_changes_| if
+      // sink_wants_.max_pixel_count_step_up will be changed since
+      // last time |source_->AddOrUpdateSink| was called. That is, this will
+      // result in a new request for the source to change resolution.
+      if (sink_wants_.max_pixel_count ||
+          (sink_wants_.max_pixel_count_step_up &&
+           *sink_wants_.max_pixel_count_step_up < *max_pixel_count_step_up)) {
+        ++number_of_cpu_adapt_changes_;
+        --cpu_restricted_counter_;
+      }
     }
-    // The input video frame size will have a resolution with less than or
-    // equal to |max_pixel_count| depending on how the source can scale the
-    // input frame size.
-    max_pixel_count = rtc::Optional<int>(
-        (last_frame_info_.height * last_frame_info_.width * 3) / 5);
-    // Increase |number_of_cpu_adapt_changes_| if
-    // sink_wants_.max_pixel_count will be changed since
-    // last time |source_->AddOrUpdateSink| was called. That is, this will
-    // result in a new request for the source to change resolution.
-    if (!sink_wants_.max_pixel_count ||
-        *sink_wants_.max_pixel_count > *max_pixel_count) {
-      ++number_of_cpu_adapt_changes_;
-      ++cpu_restricted_counter_;
-    }
-  } else {
-    RTC_DCHECK(load == kUnderuse);
-    rtc::CritScope cs(&lock_);
-    // The input video frame size will have a resolution with "one step up"
-    // pixels than |max_pixel_count_step_up| where "one step up" depends on
-    // how the source can scale the input frame size.
-    max_pixel_count_step_up =
-        rtc::Optional<int>(last_frame_info_.height * last_frame_info_.width);
-    // Increase |number_of_cpu_adapt_changes_| if
-    // sink_wants_.max_pixel_count_step_up will be changed since
-    // last time |source_->AddOrUpdateSink| was called. That is, this will
-    // result in a new request for the source to change resolution.
-    if (sink_wants_.max_pixel_count ||
-        (sink_wants_.max_pixel_count_step_up &&
-         *sink_wants_.max_pixel_count_step_up < *max_pixel_count_step_up)) {
-      ++number_of_cpu_adapt_changes_;
-      --cpu_restricted_counter_;
-    }
+    sink_wants_.max_pixel_count = max_pixel_count;
+    sink_wants_.max_pixel_count_step_up = max_pixel_count_step_up;
   }
-  sink_wants_.max_pixel_count = max_pixel_count;
-  sink_wants_.max_pixel_count_step_up = max_pixel_count_step_up;
   // |source_->AddOrUpdateSink| may not be called while holding |lock_| since
   // that might cause a lock order inversion.
   source_->AddOrUpdateSink(this, sink_wants_);
@@ -2132,17 +2143,21 @@
 VideoSenderInfo WebRtcVideoChannel2::WebRtcVideoSendStream::GetVideoSenderInfo(
     bool log_stats) {
   VideoSenderInfo info;
-  RTC_DCHECK_RUN_ON(&thread_checker_);
-  for (uint32_t ssrc : parameters_.config.rtp.ssrcs)
-    info.add_ssrc(ssrc);
+  webrtc::VideoSendStream::Stats stats;
+  RTC_DCHECK(thread_checker_.CalledOnValidThread());
+  {
+    rtc::CritScope cs(&lock_);
+    for (uint32_t ssrc : parameters_.config.rtp.ssrcs)
+      info.add_ssrc(ssrc);
 
-  if (parameters_.codec_settings)
-    info.codec_name = parameters_.codec_settings->codec.name;
+    if (parameters_.codec_settings)
+      info.codec_name = parameters_.codec_settings->codec.name;
 
-  if (stream_ == NULL)
-    return info;
+    if (stream_ == NULL)
+      return info;
 
-  webrtc::VideoSendStream::Stats stats = stream_->GetStats();
+    stats = stream_->GetStats();
+  }
 
   if (log_stats)
     LOG(LS_INFO) << stats.ToString(rtc::TimeMillis());
@@ -2203,7 +2218,7 @@
 
 void WebRtcVideoChannel2::WebRtcVideoSendStream::FillBandwidthEstimationInfo(
     BandwidthEstimationInfo* bwe_info) {
-  RTC_DCHECK_RUN_ON(&thread_checker_);
+  rtc::CritScope cs(&lock_);
   if (stream_ == NULL) {
     return;
   }
@@ -2219,7 +2234,6 @@
 }
 
 void WebRtcVideoChannel2::WebRtcVideoSendStream::RecreateWebRtcStream() {
-  RTC_DCHECK_RUN_ON(&thread_checker_);
   if (stream_ != NULL) {
     call_->DestroyVideoSendStream(stream_);
   }
@@ -2243,6 +2257,7 @@
   stream_->SetSource(this);
 
   parameters_.encoder_config.encoder_specific_settings = NULL;
+  pending_encoder_reconfiguration_ = false;
 
   // Call stream_->Start() if necessary conditions are met.
   UpdateSendState();
diff --git a/webrtc/media/engine/webrtcvideoengine2.h b/webrtc/media/engine/webrtcvideoengine2.h
index 38e0eaa..2ad4ed8 100644
--- a/webrtc/media/engine/webrtcvideoengine2.h
+++ b/webrtc/media/engine/webrtcvideoengine2.h
@@ -320,13 +320,17 @@
       bool external;
     };
 
-    // TODO(perkj): VideoFrameInfo is currently used for CPU adaptation since
-    // we currently do not express CPU overuse using SinkWants in lower
-    // layers. This will be fixed in an upcoming cl.
     struct VideoFrameInfo {
+      // Initial encoder configuration (QCIF, 176x144) frame (to ensure that
+      // hardware encoders can be initialized). This gives us low memory usage
+      // but also makes it so configuration errors are discovered at the time we
+      // apply the settings rather than when we get the first frame (waiting for
+      // the first frame to know that you gave a bad codec parameter could make
+      // debugging hard).
+      // TODO(pbos): Consider setting up encoders lazily.
       VideoFrameInfo()
-          : width(0),
-            height(0),
+          : width(176),
+            height(144),
             rotation(webrtc::kVideoRotation_0),
             is_texture(false) {}
       int width;
@@ -335,63 +339,79 @@
       bool is_texture;
     };
 
+    static std::vector<webrtc::VideoStream> CreateVideoStreams(
+        const VideoCodec& codec,
+        const VideoOptions& options,
+        int max_bitrate_bps,
+        size_t num_streams);
+    static std::vector<webrtc::VideoStream> CreateSimulcastVideoStreams(
+        const VideoCodec& codec,
+        const VideoOptions& options,
+        int max_bitrate_bps,
+        size_t num_streams);
+
     rtc::scoped_refptr<webrtc::VideoEncoderConfig::EncoderSpecificSettings>
-    ConfigureVideoEncoderSettings(const VideoCodec& codec);
-    AllocatedEncoder CreateVideoEncoder(const VideoCodec& codec);
-    void DestroyVideoEncoder(AllocatedEncoder* encoder);
-    void SetCodec(const VideoCodecSettings& codec);
-    void RecreateWebRtcStream();
+    ConfigureVideoEncoderSettings(const VideoCodec& codec)
+        EXCLUSIVE_LOCKS_REQUIRED(lock_);
+
+    AllocatedEncoder CreateVideoEncoder(const VideoCodec& codec)
+        EXCLUSIVE_LOCKS_REQUIRED(lock_);
+    void DestroyVideoEncoder(AllocatedEncoder* encoder)
+        EXCLUSIVE_LOCKS_REQUIRED(lock_);
+    void SetCodec(const VideoCodecSettings& codec)
+        EXCLUSIVE_LOCKS_REQUIRED(lock_);
+    void RecreateWebRtcStream() EXCLUSIVE_LOCKS_REQUIRED(lock_);
     webrtc::VideoEncoderConfig CreateVideoEncoderConfig(
-        const VideoCodec& codec) const;
-    void ReconfigureEncoder();
+        const VideoCodec& codec) const EXCLUSIVE_LOCKS_REQUIRED(lock_);
+    void ReconfigureEncoder() EXCLUSIVE_LOCKS_REQUIRED(lock_);
     bool ValidateRtpParameters(const webrtc::RtpParameters& parameters);
 
     // Calls Start or Stop according to whether or not |sending_| is true,
     // and whether or not the encoding in |rtp_parameters_| is active.
-    void UpdateSendState();
+    void UpdateSendState() EXCLUSIVE_LOCKS_REQUIRED(lock_);
 
     void UpdateHistograms() const EXCLUSIVE_LOCKS_REQUIRED(lock_);
 
     rtc::ThreadChecker thread_checker_;
     rtc::AsyncInvoker invoker_;
     rtc::Thread* worker_thread_;
-    const std::vector<uint32_t> ssrcs_ ACCESS_ON(&thread_checker_);
-    const std::vector<SsrcGroup> ssrc_groups_ ACCESS_ON(&thread_checker_);
+    const std::vector<uint32_t> ssrcs_;
+    const std::vector<SsrcGroup> ssrc_groups_;
     webrtc::Call* const call_;
-    rtc::VideoSinkWants sink_wants_ ACCESS_ON(&thread_checker_);
+    rtc::VideoSinkWants sink_wants_;
     // Counter used for deciding if the video resolution is currently
     // restricted by CPU usage. It is reset if |source_| is changed.
     int cpu_restricted_counter_;
     // Total number of times resolution as been requested to be changed due to
     // CPU adaptation.
-    int number_of_cpu_adapt_changes_ ACCESS_ON(&thread_checker_);
+    int number_of_cpu_adapt_changes_;
     // Total number of frames sent to |stream_|.
     int frame_count_ GUARDED_BY(lock_);
     // Total number of cpu restricted frames sent to |stream_|.
     int cpu_restricted_frame_count_ GUARDED_BY(lock_);
-    rtc::VideoSourceInterface<cricket::VideoFrame>* source_
-        ACCESS_ON(&thread_checker_);
+    rtc::VideoSourceInterface<cricket::VideoFrame>* source_;
     WebRtcVideoEncoderFactory* const external_encoder_factory_
-        ACCESS_ON(&thread_checker_);
+        GUARDED_BY(lock_);
 
     rtc::CriticalSection lock_;
-    webrtc::VideoSendStream* stream_ ACCESS_ON(&thread_checker_);
+    webrtc::VideoSendStream* stream_ GUARDED_BY(lock_);
     rtc::VideoSinkInterface<webrtc::VideoFrame>* encoder_sink_
         GUARDED_BY(lock_);
     // Contains settings that are the same for all streams in the MediaChannel,
     // such as codecs, header extensions, and the global bitrate limit for the
     // entire channel.
-    VideoSendStreamParameters parameters_ ACCESS_ON(&thread_checker_);
+    VideoSendStreamParameters parameters_ GUARDED_BY(lock_);
     // Contains settings that are unique for each stream, such as max_bitrate.
     // Does *not* contain codecs, however.
     // TODO(skvlad): Move ssrcs_ and ssrc_groups_ into rtp_parameters_.
     // TODO(skvlad): Combine parameters_ and rtp_parameters_ once we have only
     // one stream per MediaChannel.
-    webrtc::RtpParameters rtp_parameters_ ACCESS_ON(&thread_checker_);
-    AllocatedEncoder allocated_encoder_ ACCESS_ON(&thread_checker_);
+    webrtc::RtpParameters rtp_parameters_ GUARDED_BY(lock_);
+    bool pending_encoder_reconfiguration_ GUARDED_BY(lock_);
+    AllocatedEncoder allocated_encoder_ GUARDED_BY(lock_);
     VideoFrameInfo last_frame_info_ GUARDED_BY(lock_);
 
-    bool sending_ ACCESS_ON(&thread_checker_);
+    bool sending_ GUARDED_BY(lock_);
 
     // The timestamp of the last frame received
     // Used to generate timestamp for the black frame when source is removed
diff --git a/webrtc/media/engine/webrtcvideoengine2_unittest.cc b/webrtc/media/engine/webrtcvideoengine2_unittest.cc
index d482509..955fd35 100644
--- a/webrtc/media/engine/webrtcvideoengine2_unittest.cc
+++ b/webrtc/media/engine/webrtcvideoengine2_unittest.cc
@@ -1077,16 +1077,22 @@
     return AddSendStream(CreateSimStreamParams("cname", ssrcs));
   }
 
-  int GetMaxEncoderBitrate() {
+  int GetMaxEncoderBitrate(cricket::FakeVideoCapturer& capturer) {
+    EXPECT_TRUE(capturer.CaptureFrame());
+
     std::vector<FakeVideoSendStream*> streams =
         fake_call_->GetVideoSendStreams();
-    EXPECT_EQ(1u, streams.size());
+    EXPECT_TRUE(streams.size() > 0);
     FakeVideoSendStream* stream = streams[streams.size() - 1];
-    EXPECT_EQ(1, stream->GetEncoderConfig().number_of_streams);
-    return stream->GetVideoStreams()[0].max_bitrate_bps;
+
+    webrtc::VideoEncoderConfig encoder_config =
+        stream->GetEncoderConfig().Copy();
+    EXPECT_EQ(1, encoder_config.streams.size());
+    return encoder_config.streams[0].max_bitrate_bps;
   }
 
-  void SetAndExpectMaxBitrate(int global_max,
+  void SetAndExpectMaxBitrate(cricket::FakeVideoCapturer& capturer,
+                              int global_max,
                               int stream_max,
                               int expected_encoder_bitrate) {
     VideoSendParameters limited_send_params = send_parameters_;
@@ -1102,7 +1108,7 @@
     EXPECT_EQ(1UL, parameters.encodings.size());
     EXPECT_EQ(stream_max, parameters.encodings[0].max_bitrate_bps);
     // Verify that the new value propagated down to the encoder
-    EXPECT_EQ(expected_encoder_bitrate, GetMaxEncoderBitrate());
+    EXPECT_EQ(expected_encoder_bitrate, GetMaxEncoderBitrate(capturer));
   }
 
   std::unique_ptr<FakeCall> fake_call_;
@@ -1514,10 +1520,10 @@
 
   FakeVideoSendStream* stream = AddSendStream();
 
-  // No frames entered.
+  // No frames entered, using default dimensions.
   std::vector<webrtc::VideoStream> streams = stream->GetVideoStreams();
-  EXPECT_EQ(0u, streams[0].width);
-  EXPECT_EQ(0u, streams[0].height);
+  EXPECT_EQ(176u, streams[0].width);
+  EXPECT_EQ(144u, streams[0].height);
 
   cricket::FakeVideoCapturer capturer;
   EXPECT_TRUE(channel_->SetVideoSend(last_ssrc_, true, nullptr, &capturer));
@@ -1529,6 +1535,8 @@
   streams = stream->GetVideoStreams();
   EXPECT_EQ(kVp8Codec720p.width, streams[0].width);
   EXPECT_EQ(kVp8Codec720p.height, streams[0].height);
+  // No frames should have been actually put in there though.
+  EXPECT_EQ(0, stream->GetNumberOfSwappedFrames());
 
   EXPECT_TRUE(channel_->SetVideoSend(last_ssrc_, true, nullptr, nullptr));
 }
@@ -1566,9 +1574,8 @@
       send_stream->GetEncoderConfig().Copy();
   EXPECT_EQ(webrtc::VideoEncoderConfig::ContentType::kRealtimeVideo,
             encoder_config.content_type);
-  std::vector<webrtc::VideoStream> streams = send_stream->GetVideoStreams();
-  EXPECT_EQ(capture_format_hd.width, streams.front().width);
-  EXPECT_EQ(capture_format_hd.height, streams.front().height);
+  EXPECT_EQ(codec.width, encoder_config.streams.front().width);
+  EXPECT_EQ(codec.height, encoder_config.streams.front().height);
   EXPECT_EQ(0, encoder_config.min_transmit_bitrate_bps)
       << "Non-screenshare shouldn't use min-transmit bitrate.";
 
@@ -1591,10 +1598,10 @@
   EXPECT_EQ(kScreenshareMinBitrateKbps * 1000,
             encoder_config.min_transmit_bitrate_bps);
 
-  streams = send_stream->GetVideoStreams();
-  EXPECT_EQ(capture_format_hd.width, streams.front().width);
-  EXPECT_EQ(capture_format_hd.height, streams.front().height);
-  EXPECT_TRUE(streams[0].temporal_layer_thresholds_bps.empty());
+  EXPECT_EQ(capture_format_hd.width, encoder_config.streams.front().width);
+  EXPECT_EQ(capture_format_hd.height, encoder_config.streams.front().height);
+  EXPECT_TRUE(encoder_config.streams[0].temporal_layer_thresholds_bps.empty());
+
   EXPECT_TRUE(channel_->SetVideoSend(last_ssrc_, true, nullptr, nullptr));
 }
 
@@ -1678,12 +1685,10 @@
   encoder_config = send_stream->GetEncoderConfig().Copy();
   EXPECT_EQ(webrtc::VideoEncoderConfig::ContentType::kScreen,
             encoder_config.content_type);
-
-  std::vector<webrtc::VideoStream> streams = send_stream->GetVideoStreams();
-  ASSERT_EQ(1u, streams.size());
-  ASSERT_EQ(1u, streams[0].temporal_layer_thresholds_bps.size());
+  ASSERT_EQ(1u, encoder_config.streams.size());
+  ASSERT_EQ(1u, encoder_config.streams[0].temporal_layer_thresholds_bps.size());
   EXPECT_EQ(kConferenceScreencastTemporalBitrateBps,
-            streams[0].temporal_layer_thresholds_bps[0]);
+            encoder_config.streams[0].temporal_layer_thresholds_bps[0]);
 
   EXPECT_TRUE(channel_->SetVideoSend(last_ssrc_, true, nullptr, nullptr));
 }
@@ -1801,27 +1806,18 @@
   VideoOptions options;
   cricket::FakeVideoCapturer capturer;
 
-  AddSendStream();
+  FakeVideoSendStream* send_stream = AddSendStream();
   EXPECT_EQ(cricket::CS_RUNNING,
             capturer.Start(capturer.GetSupportedFormats()->front()));
-  cricket::VideoSendParameters parameters;
-  parameters.codecs.push_back(kVp8Codec720p);
-  ASSERT_TRUE(channel_->SetSendParameters(parameters));
-  FakeVideoSendStream* send_stream = fake_call_->GetVideoSendStreams().front();
-
-  EXPECT_TRUE(channel_->SetVideoSend(last_ssrc_, true, &options, &capturer));
   EXPECT_TRUE(channel_->SetVideoSend(last_ssrc_, true, &options, &capturer));
   EXPECT_TRUE(capturer.CaptureFrame());
-  // Expect 1 reconfigurations at this point from the initial configuration.
-  EXPECT_EQ(1, send_stream->num_encoder_reconfigurations());
+  // Expect 2 reconfigurations at this point, from the initial configuration
+  // and from the dimensions of the first frame.
+  EXPECT_EQ(2, send_stream->num_encoder_reconfigurations());
 
   // Set the options one more time and expect no additional reconfigurations.
   EXPECT_TRUE(channel_->SetVideoSend(last_ssrc_, true, &options, &capturer));
-  EXPECT_EQ(1, send_stream->num_encoder_reconfigurations());
-
-  // Change |options| and expect 2 reconfigurations.
-  options.is_screencast = rtc::Optional<bool>(true);
-  EXPECT_TRUE(channel_->SetVideoSend(last_ssrc_, true, &options, &capturer));
+  EXPECT_TRUE(capturer.CaptureFrame());
   EXPECT_EQ(2, send_stream->num_encoder_reconfigurations());
 
   EXPECT_TRUE(channel_->SetVideoSend(last_ssrc_, true, nullptr, nullptr));
@@ -2314,26 +2310,28 @@
 
 TEST_F(WebRtcVideoChannel2Test, SetSendCodecsChangesExistingStreams) {
   cricket::VideoSendParameters parameters;
-  cricket::VideoCodec codec720p(100, "VP8", 1280, 720, 30);
-  codec720p.SetParam(kCodecParamMaxQuantization, kDefaultQpMax);
-  parameters.codecs.push_back(codec720p);
-
+  parameters.codecs.push_back(kVp8Codec720p);
   ASSERT_TRUE(channel_->SetSendParameters(parameters));
   channel_->SetSend(true);
 
   FakeVideoSendStream* stream = AddSendStream();
+
   cricket::FakeVideoCapturer capturer;
   EXPECT_TRUE(channel_->SetVideoSend(last_ssrc_, true, nullptr, &capturer));
+  EXPECT_EQ(cricket::CS_RUNNING,
+            capturer.Start(capturer.GetSupportedFormats()->front()));
+  EXPECT_TRUE(capturer.CaptureFrame());
 
   std::vector<webrtc::VideoStream> streams = stream->GetVideoStreams();
-  EXPECT_EQ(kDefaultQpMax, streams[0].max_qp);
+  EXPECT_EQ(kVp8Codec720p.width, streams[0].width);
+  EXPECT_EQ(kVp8Codec720p.height, streams[0].height);
 
   parameters.codecs.clear();
-  codec720p.SetParam(kCodecParamMaxQuantization, kDefaultQpMax + 1);
-  parameters.codecs.push_back(codec720p);
+  parameters.codecs.push_back(kVp8Codec360p);
   ASSERT_TRUE(channel_->SetSendParameters(parameters));
   streams = fake_call_->GetVideoSendStreams()[0]->GetVideoStreams();
-  EXPECT_EQ(kDefaultQpMax + 1, streams[0].max_qp);
+  EXPECT_EQ(kVp8Codec360p.width, streams[0].width);
+  EXPECT_EQ(kVp8Codec360p.height, streams[0].height);
   EXPECT_TRUE(channel_->SetVideoSend(last_ssrc_, true, nullptr, nullptr));
 }
 
@@ -3418,9 +3416,8 @@
   EXPECT_EQ(720, capture_format_hd.height);
   EXPECT_EQ(cricket::CS_RUNNING, capturer.Start(capture_format_hd));
   EXPECT_TRUE(channel_->SetSend(true));
-  capturer.CaptureFrame();
 
-  int default_encoder_bitrate = GetMaxEncoderBitrate();
+  int default_encoder_bitrate = GetMaxEncoderBitrate(capturer);
   EXPECT_TRUE(default_encoder_bitrate > 1000);
 
   // TODO(skvlad): Resolve the inconsistency between the interpretation
@@ -3431,11 +3428,11 @@
   //          max_bandwidth_bps = -1 - do not change the previously set
   //                                   limit.
 
-  SetAndExpectMaxBitrate(1000, 0, 1000);
-  SetAndExpectMaxBitrate(1000, 800, 800);
-  SetAndExpectMaxBitrate(600, 800, 600);
-  SetAndExpectMaxBitrate(0, 800, 800);
-  SetAndExpectMaxBitrate(0, 0, default_encoder_bitrate);
+  SetAndExpectMaxBitrate(capturer, 1000, 0, 1000);
+  SetAndExpectMaxBitrate(capturer, 1000, 800, 800);
+  SetAndExpectMaxBitrate(capturer, 600, 800, 600);
+  SetAndExpectMaxBitrate(capturer, 0, 800, 800);
+  SetAndExpectMaxBitrate(capturer, 0, 0, default_encoder_bitrate);
 
   EXPECT_TRUE(channel_->SetVideoSend(last_ssrc_, true, nullptr, nullptr));
 }
diff --git a/webrtc/test/call_test.cc b/webrtc/test/call_test.cc
index 519c899..d6cbaa6 100644
--- a/webrtc/test/call_test.cc
+++ b/webrtc/test/call_test.cc
@@ -11,6 +11,7 @@
 #include "webrtc/config.h"
 #include "webrtc/modules/audio_coding/codecs/builtin_audio_decoder_factory.h"
 #include "webrtc/test/call_test.h"
+#include "webrtc/test/encoder_settings.h"
 #include "webrtc/test/testsupport/fileutils.h"
 #include "webrtc/voice_engine/include/voe_base.h"
 #include "webrtc/voice_engine/include/voe_codec.h"
@@ -94,11 +95,7 @@
   }
 
   if (num_video_streams_ > 0) {
-    int width = kDefaultWidth;
-    int height = kDefaultHeight;
-    int frame_rate = kDefaultFramerate;
-    test->ModifyVideoCaptureStartResolution(&width, &height, &frame_rate);
-    CreateFrameGeneratorCapturer(frame_rate, width, height);
+    CreateFrameGeneratorCapturer();
     test->OnFrameGeneratorCapturerCreated(frame_generator_capturer_.get());
   }
 
@@ -189,8 +186,7 @@
         kFakeVideoSendPayloadType;
     video_send_config_.rtp.extensions.push_back(
         RtpExtension(RtpExtension::kAbsSendTimeUri, kAbsSendTimeExtensionId));
-    FillEncoderConfiguration(num_video_streams, &video_encoder_config_);
-
+    video_encoder_config_.streams = test::CreateVideoStreams(num_video_streams);
     for (size_t i = 0; i < num_video_streams; ++i)
       video_send_config_.rtp.ssrcs.push_back(kVideoSendSsrcs[i]);
     video_send_config_.rtp.extensions.push_back(RtpExtension(
@@ -240,20 +236,17 @@
 }
 
 void CallTest::CreateFrameGeneratorCapturerWithDrift(Clock* clock,
-                                                     float speed,
-                                                     int framerate,
-                                                     int width,
-                                                     int height) {
+                                                     float speed) {
+  VideoStream stream = video_encoder_config_.streams.back();
   frame_generator_capturer_.reset(test::FrameGeneratorCapturer::Create(
-      width, height, framerate * speed, clock));
+      stream.width, stream.height, stream.max_framerate * speed, clock));
   video_send_stream_->SetSource(frame_generator_capturer_.get());
 }
 
-void CallTest::CreateFrameGeneratorCapturer(int framerate,
-                                            int width,
-                                            int height) {
-  frame_generator_capturer_.reset(
-      test::FrameGeneratorCapturer::Create(width, height, framerate, clock_));
+void CallTest::CreateFrameGeneratorCapturer() {
+  VideoStream stream = video_encoder_config_.streams.back();
+  frame_generator_capturer_.reset(test::FrameGeneratorCapturer::Create(
+      stream.width, stream.height, stream.max_framerate, clock_));
   video_send_stream_->SetSource(frame_generator_capturer_.get());
 }
 
@@ -353,9 +346,6 @@
   voe_recv_.voice_engine = nullptr;
 }
 
-const int CallTest::kDefaultWidth;
-const int CallTest::kDefaultHeight;
-const int CallTest::kDefaultFramerate;
 const int CallTest::kDefaultTimeoutMs = 30 * 1000;
 const int CallTest::kLongTimeoutMs = 120 * 1000;
 const uint8_t CallTest::kVideoSendPayloadType = 100;
@@ -414,10 +404,6 @@
     std::vector<VideoReceiveStream::Config>* receive_configs,
     VideoEncoderConfig* encoder_config) {}
 
-void BaseTest::ModifyVideoCaptureStartResolution(int* width,
-                                                 int* heigt,
-                                                 int* frame_rate) {}
-
 void BaseTest::OnVideoStreamsCreated(
     VideoSendStream* send_stream,
     const std::vector<VideoReceiveStream*>& receive_streams) {}
diff --git a/webrtc/test/call_test.h b/webrtc/test/call_test.h
index f8d52ac..d8019e5 100644
--- a/webrtc/test/call_test.h
+++ b/webrtc/test/call_test.h
@@ -14,7 +14,6 @@
 #include <vector>
 
 #include "webrtc/call.h"
-#include "webrtc/test/encoder_settings.h"
 #include "webrtc/test/fake_audio_device.h"
 #include "webrtc/test/fake_decoder.h"
 #include "webrtc/test/fake_encoder.h"
@@ -36,9 +35,7 @@
   virtual ~CallTest();
 
   static const size_t kNumSsrcs = 3;
-  static const int kDefaultWidth = 320;
-  static const int kDefaultHeight = 180;
-  static const int kDefaultFramerate = 30;
+
   static const int kDefaultTimeoutMs;
   static const int kLongTimeoutMs;
   static const uint8_t kVideoSendPayloadType;
@@ -72,12 +69,8 @@
                         Transport* send_transport);
   void CreateMatchingReceiveConfigs(Transport* rtcp_send_transport);
 
-  void CreateFrameGeneratorCapturerWithDrift(Clock* drift_clock,
-                                             float speed,
-                                             int framerate,
-                                             int width,
-                                             int height);
-  void CreateFrameGeneratorCapturer(int framerate, int width, int height);
+  void CreateFrameGeneratorCapturerWithDrift(Clock* drift_clock, float speed);
+  void CreateFrameGeneratorCapturer();
   void CreateFakeAudioDevices();
 
   void CreateVideoStreams();
@@ -161,9 +154,6 @@
       VideoSendStream::Config* send_config,
       std::vector<VideoReceiveStream::Config>* receive_configs,
       VideoEncoderConfig* encoder_config);
-  virtual void ModifyVideoCaptureStartResolution(int* width,
-                                                 int* heigt,
-                                                 int* frame_rate);
   virtual void OnVideoStreamsCreated(
       VideoSendStream* send_stream,
       const std::vector<VideoReceiveStream*>& receive_streams);
diff --git a/webrtc/test/encoder_settings.cc b/webrtc/test/encoder_settings.cc
index 80c42ef..64339df 100644
--- a/webrtc/test/encoder_settings.cc
+++ b/webrtc/test/encoder_settings.cc
@@ -9,76 +9,50 @@
  */
 #include "webrtc/test/encoder_settings.h"
 
-#include <algorithm>
-#include <string>
+#include <assert.h>
+#include <string.h>
 
 #include "webrtc/test/fake_decoder.h"
 #include "webrtc/video_decoder.h"
 
 namespace webrtc {
 namespace test {
+std::vector<VideoStream> CreateVideoStreams(size_t num_streams) {
+  assert(num_streams > 0);
 
-const size_t DefaultVideoStreamFactory::kMaxNumberOfStreams;
-const int DefaultVideoStreamFactory::kMaxBitratePerStream[] = {150000, 450000,
-                                                               1500000};
-const int DefaultVideoStreamFactory::kDefaultMinBitratePerStream[] = {
-    50000, 200000, 700000};
+  // Add more streams to the settings above with reasonable values if required.
+  static const size_t kNumSettings = 3;
+  assert(num_streams <= kNumSettings);
 
-// static
-std::vector<VideoStream> CreateVideoStreams(
-    int width,
-    int height,
-    const webrtc::VideoEncoderConfig& encoder_config) {
-  RTC_DCHECK(encoder_config.number_of_streams <=
-             DefaultVideoStreamFactory::kMaxNumberOfStreams);
+  std::vector<VideoStream> stream_settings(kNumSettings);
 
-  std::vector<VideoStream> stream_settings(encoder_config.number_of_streams);
-  int bitrate_left_bps = encoder_config.max_bitrate_bps;
+  stream_settings[0].width = 320;
+  stream_settings[0].height = 180;
+  stream_settings[0].max_framerate = 30;
+  stream_settings[0].min_bitrate_bps = 50000;
+  stream_settings[0].target_bitrate_bps = stream_settings[0].max_bitrate_bps =
+      150000;
+  stream_settings[0].max_qp = 56;
 
-  for (size_t i = 0; i < encoder_config.number_of_streams; ++i) {
-    stream_settings[i].width =
-        (i + 1) * width / encoder_config.number_of_streams;
-    stream_settings[i].height =
-        (i + 1) * height / encoder_config.number_of_streams;
-    stream_settings[i].max_framerate = 30;
-    stream_settings[i].min_bitrate_bps =
-        DefaultVideoStreamFactory::kDefaultMinBitratePerStream[i];
-    stream_settings[i].target_bitrate_bps = stream_settings[i].max_bitrate_bps =
-        std::min(bitrate_left_bps,
-                 DefaultVideoStreamFactory::kMaxBitratePerStream[i]);
-    stream_settings[i].max_qp = 56;
-    bitrate_left_bps -= stream_settings[i].target_bitrate_bps;
-  }
+  stream_settings[1].width = 640;
+  stream_settings[1].height = 360;
+  stream_settings[1].max_framerate = 30;
+  stream_settings[1].min_bitrate_bps = 200000;
+  stream_settings[1].target_bitrate_bps = stream_settings[1].max_bitrate_bps =
+      450000;
+  stream_settings[1].max_qp = 56;
 
-  stream_settings[encoder_config.number_of_streams - 1].max_bitrate_bps +=
-      bitrate_left_bps;
-
+  stream_settings[2].width = 1280;
+  stream_settings[2].height = 720;
+  stream_settings[2].max_framerate = 30;
+  stream_settings[2].min_bitrate_bps = 700000;
+  stream_settings[2].target_bitrate_bps = stream_settings[2].max_bitrate_bps =
+      1500000;
+  stream_settings[2].max_qp = 56;
+  stream_settings.resize(num_streams);
   return stream_settings;
 }
 
-DefaultVideoStreamFactory::DefaultVideoStreamFactory() {}
-
-std::vector<VideoStream> DefaultVideoStreamFactory::CreateEncoderStreams(
-    int width,
-    int height,
-    const webrtc::VideoEncoderConfig& encoder_config) {
-  return CreateVideoStreams(width, height, encoder_config);
-}
-
-void FillEncoderConfiguration(size_t num_streams,
-                              VideoEncoderConfig* configuration) {
-  RTC_DCHECK_LE(num_streams, DefaultVideoStreamFactory::kMaxNumberOfStreams);
-
-  configuration->number_of_streams = num_streams;
-  configuration->video_stream_factory =
-      new rtc::RefCountedObject<DefaultVideoStreamFactory>();
-  configuration->max_bitrate_bps = 0;
-  for (size_t i = 0; i < num_streams; ++i) {
-    configuration->max_bitrate_bps +=
-        DefaultVideoStreamFactory::kMaxBitratePerStream[i];
-  }
-}
-
 VideoReceiveStream::Decoder CreateMatchingDecoder(
     const VideoSendStream::Config::EncoderSettings& encoder_settings) {
   VideoReceiveStream::Decoder decoder;
diff --git a/webrtc/test/encoder_settings.h b/webrtc/test/encoder_settings.h
index 82d8c5f..a44d366 100644
--- a/webrtc/test/encoder_settings.h
+++ b/webrtc/test/encoder_settings.h
@@ -10,43 +10,12 @@
 #ifndef WEBRTC_TEST_ENCODER_SETTINGS_H_
 #define WEBRTC_TEST_ENCODER_SETTINGS_H_
 
-#include <vector>
-
 #include "webrtc/video_receive_stream.h"
 #include "webrtc/video_send_stream.h"
 
 namespace webrtc {
 namespace test {
-
-class DefaultVideoStreamFactory
-    : public VideoEncoderConfig::VideoStreamFactoryInterface {
- public:
-  DefaultVideoStreamFactory();
-
-  static const size_t kMaxNumberOfStreams = 3;
-  // Defined as {150000, 450000, 1500000};
-  static const int kMaxBitratePerStream[];
-  // Defined as {50000, 200000, 700000};
-  static const int kDefaultMinBitratePerStream[];
-
- private:
-  std::vector<VideoStream> CreateEncoderStreams(
-      int width,
-      int height,
-      const VideoEncoderConfig& encoder_config) override;
-};
-
-// Creates |encoder_config.number_of_streams| VideoStreams where index
-// |encoder_config.number_of_streams -1| have width = |width|, height =
-// |height|. The total max bitrate of all VideoStreams is
-// |encoder_config.max_bitrate_bps|.
-std::vector<VideoStream> CreateVideoStreams(
-    int width,
-    int height,
-    const webrtc::VideoEncoderConfig& encoder_config);
-
-void FillEncoderConfiguration(size_t num_streams,
-                              VideoEncoderConfig* configuration);
+std::vector<VideoStream> CreateVideoStreams(size_t num_streams);
 
 VideoReceiveStream::Decoder CreateMatchingDecoder(
     const VideoSendStream::Config::EncoderSettings& encoder_settings);
diff --git a/webrtc/test/frame_generator.cc b/webrtc/test/frame_generator.cc
index b83b1be..27935e4 100644
--- a/webrtc/test/frame_generator.cc
+++ b/webrtc/test/frame_generator.cc
@@ -26,14 +26,8 @@
 
 class ChromaGenerator : public FrameGenerator {
  public:
-  ChromaGenerator(size_t width, size_t height) : angle_(0.0) {
-    ChangeResolution(width, height);
-  }
-
-  void ChangeResolution(size_t width, size_t height) override {
-    rtc::CritScope lock(&crit_);
-    width_ = width;
-    height_ = height;
+  ChromaGenerator(size_t width, size_t height)
+      : angle_(0.0), width_(width), height_(height) {
     RTC_CHECK(width_ > 0);
     RTC_CHECK(height_ > 0);
     half_width_ = (width_ + 1) / 2;
@@ -42,7 +36,6 @@
   }
 
   VideoFrame* NextFrame() override {
-    rtc::CritScope lock(&crit_);
     angle_ += 30.0;
     uint8_t u = fabs(sin(angle_)) * 0xFF;
     uint8_t v = fabs(cos(angle_)) * 0xFF;
@@ -62,14 +55,13 @@
   }
 
  private:
-  rtc::CriticalSection crit_;
-  double angle_ GUARDED_BY(&crit_);
-  size_t width_ GUARDED_BY(&crit_);
-  size_t height_ GUARDED_BY(&crit_);
-  size_t half_width_ GUARDED_BY(&crit_);
-  size_t y_size_ GUARDED_BY(&crit_);
-  size_t uv_size_ GUARDED_BY(&crit_);
-  std::unique_ptr<VideoFrame> frame_ GUARDED_BY(&crit_);
+  double angle_;
+  size_t width_;
+  size_t height_;
+  size_t half_width_;
+  size_t y_size_;
+  size_t uv_size_;
+  std::unique_ptr<VideoFrame> frame_;
 };
 
 class YuvFileGenerator : public FrameGenerator {
diff --git a/webrtc/test/frame_generator.h b/webrtc/test/frame_generator.h
index e7cba1c..fc3f306 100644
--- a/webrtc/test/frame_generator.h
+++ b/webrtc/test/frame_generator.h
@@ -49,11 +49,6 @@
   // Returns video frame that remains valid until next call.
   virtual VideoFrame* NextFrame() = 0;
 
-  // Change the capture resolution.
-  virtual void ChangeResolution(size_t width, size_t height) {
-    RTC_NOTREACHED();
-  }
-
   // Creates a test frame generator that creates fully saturated frames with
   // varying U, V values over time.
   static FrameGenerator* CreateChromaGenerator(size_t width, size_t height);
diff --git a/webrtc/test/frame_generator_capturer.cc b/webrtc/test/frame_generator_capturer.cc
index d80154a..7e92909 100644
--- a/webrtc/test/frame_generator_capturer.cc
+++ b/webrtc/test/frame_generator_capturer.cc
@@ -124,11 +124,6 @@
   sending_ = false;
 }
 
-void FrameGeneratorCapturer::ChangeResolution(size_t width, size_t height) {
-  rtc::CritScope cs(&lock_);
-  frame_generator_->ChangeResolution(width, height);
-}
-
 void FrameGeneratorCapturer::AddOrUpdateSink(
     rtc::VideoSinkInterface<VideoFrame>* sink,
     const rtc::VideoSinkWants& wants) {
diff --git a/webrtc/test/frame_generator_capturer.h b/webrtc/test/frame_generator_capturer.h
index fa001c4..2b2cfbc 100644
--- a/webrtc/test/frame_generator_capturer.h
+++ b/webrtc/test/frame_generator_capturer.h
@@ -45,7 +45,6 @@
 
   void Start() override;
   void Stop() override;
-  void ChangeResolution(size_t width, size_t height);
 
   void AddOrUpdateSink(rtc::VideoSinkInterface<VideoFrame>* sink,
                        const rtc::VideoSinkWants& wants) override;
diff --git a/webrtc/video/end_to_end_tests.cc b/webrtc/video/end_to_end_tests.cc
index 67cc69f..21707ec 100644
--- a/webrtc/video/end_to_end_tests.cc
+++ b/webrtc/video/end_to_end_tests.cc
@@ -259,8 +259,9 @@
   Start();
 
   std::unique_ptr<test::FrameGenerator> frame_generator(
-      test::FrameGenerator::CreateChromaGenerator(kDefaultWidth,
-                                                  kDefaultHeight));
+      test::FrameGenerator::CreateChromaGenerator(
+          video_encoder_config_.streams[0].width,
+          video_encoder_config_.streams[0].height));
   test::FrameForwarder frame_forwarder;
   video_send_stream_->SetSource(&frame_forwarder);
   frame_forwarder.IncomingCapturedFrame(*frame_generator->NextFrame());
@@ -304,6 +305,9 @@
     send_config->encoder_settings.encoder = encoder_.get();
     send_config->encoder_settings.payload_name = payload_name_;
     send_config->encoder_settings.payload_type = 126;
+    encoder_config->streams[0].min_bitrate_bps = 50000;
+    encoder_config->streams[0].target_bitrate_bps =
+        encoder_config->streams[0].max_bitrate_bps = 2000000;
 
     (*receive_configs)[0].renderer = this;
     (*receive_configs)[0].decoders.resize(1);
@@ -789,6 +793,9 @@
       send_config->encoder_settings.encoder = encoder_.get();
       send_config->encoder_settings.payload_name = "VP8";
       send_config->encoder_settings.payload_type = kFakeVideoSendPayloadType;
+      encoder_config->streams[0].min_bitrate_bps = 50000;
+      encoder_config->streams[0].max_bitrate_bps =
+          encoder_config->streams[0].target_bitrate_bps = 2000000;
 
       (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
       (*receive_configs)[0].rtp.fec.red_payload_type = kRedPayloadType;
@@ -1114,8 +1121,7 @@
   CreateMatchingReceiveConfigs(&receive_transport);
 
   CreateVideoStreams();
-  CreateFrameGeneratorCapturer(kDefaultFramerate, kDefaultWidth,
-                               kDefaultHeight);
+  CreateFrameGeneratorCapturer();
   Start();
 
   receiver_call_->DestroyVideoReceiveStream(video_receive_streams_[0]);
@@ -1272,8 +1278,13 @@
       send_config.encoder_settings.payload_name = "VP8";
       send_config.encoder_settings.payload_type = 124;
       VideoEncoderConfig encoder_config;
-      test::FillEncoderConfiguration(1, &encoder_config);
-      encoder_config.max_bitrate_bps = 100000;
+      encoder_config.streams = test::CreateVideoStreams(1);
+      VideoStream* stream = &encoder_config.streams[0];
+      stream->width = width;
+      stream->height = height;
+      stream->max_framerate = 5;
+      stream->min_bitrate_bps = stream->target_bitrate_bps =
+          stream->max_bitrate_bps = 100000;
 
       UpdateSendConfig(i, &send_config, &encoder_config, &frame_generators[i]);
 
@@ -1551,9 +1562,11 @@
 
       // Force some padding to be sent.
       const int kPaddingBitrateBps = 50000;
-      encoder_config->max_bitrate_bps = 1000000;
+      int total_target_bitrate = 0;
+      for (const VideoStream& stream : encoder_config->streams)
+        total_target_bitrate += stream.target_bitrate_bps;
       encoder_config->min_transmit_bitrate_bps =
-          encoder_config->max_bitrate_bps + kPaddingBitrateBps;
+          total_target_bitrate + kPaddingBitrateBps;
 
       // Configure RTX for redundant payload padding.
       send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
@@ -1753,8 +1766,9 @@
   Start();
 
   std::unique_ptr<test::FrameGenerator> frame_generator(
-      test::FrameGenerator::CreateChromaGenerator(kDefaultWidth,
-                                                  kDefaultHeight));
+      test::FrameGenerator::CreateChromaGenerator(
+          video_encoder_config_.streams[0].width,
+          video_encoder_config_.streams[0].height));
   test::FrameForwarder forwarder;
   video_send_stream_->SetSource(&forwarder);
   forwarder.IncomingCapturedFrame(*frame_generator->NextFrame());
@@ -1905,7 +1919,8 @@
                        test::kTransportSequenceNumberExtensionId));
       sender_ssrc_ = send_config->rtp.ssrcs[0];
 
-      encoder_config->max_bitrate_bps = 2000000;
+      encoder_config->streams[0].max_bitrate_bps =
+          encoder_config->streams[0].target_bitrate_bps = 2000000;
 
       ASSERT_EQ(1u, receive_configs->size());
       (*receive_configs)[0].rtp.remb = false;
@@ -2246,18 +2261,24 @@
   EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.ReceivedWidthInPixels"));
   EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.ReceivedHeightInPixels"));
 
-  EXPECT_EQ(1, metrics::NumEvents(video_prefix + "InputWidthInPixels",
-                                  kDefaultWidth));
-  EXPECT_EQ(1, metrics::NumEvents(video_prefix + "InputHeightInPixels",
-                                  kDefaultHeight));
-  EXPECT_EQ(
-      1, metrics::NumEvents(video_prefix + "SentWidthInPixels", kDefaultWidth));
-  EXPECT_EQ(1, metrics::NumEvents(video_prefix + "SentHeightInPixels",
-                                  kDefaultHeight));
-  EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.ReceivedWidthInPixels",
-                                  kDefaultWidth));
-  EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.ReceivedHeightInPixels",
-                                  kDefaultHeight));
+  EXPECT_EQ(1, metrics::NumEvents(
+                   video_prefix + "InputWidthInPixels",
+                   static_cast<int>(video_encoder_config_.streams[0].width)));
+  EXPECT_EQ(1, metrics::NumEvents(
+                   video_prefix + "InputHeightInPixels",
+                   static_cast<int>(video_encoder_config_.streams[0].height)));
+  EXPECT_EQ(1, metrics::NumEvents(
+                   video_prefix + "SentWidthInPixels",
+                   static_cast<int>(video_encoder_config_.streams[0].width)));
+  EXPECT_EQ(1, metrics::NumEvents(
+                   video_prefix + "SentHeightInPixels",
+                   static_cast<int>(video_encoder_config_.streams[0].height)));
+  EXPECT_EQ(1, metrics::NumEvents(
+                   "WebRTC.Video.ReceivedWidthInPixels",
+                   static_cast<int>(video_encoder_config_.streams[0].width)));
+  EXPECT_EQ(1, metrics::NumEvents(
+                   "WebRTC.Video.ReceivedHeightInPixels",
+                   static_cast<int>(video_encoder_config_.streams[0].height)));
 
   EXPECT_EQ(1, metrics::NumSamples(video_prefix + "InputFramesPerSecond"));
   EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SentFramesPerSecond"));
@@ -2463,41 +2484,22 @@
 
     size_t GetNumVideoStreams() const override { return num_ssrcs_; }
 
-    // This test use other VideoStream settings than the the default settings
-    // implemented in DefaultVideoStreamFactory. Therefore  this test implement
-    // its own VideoEncoderConfig::VideoStreamFactoryInterface which is created
-    // in ModifyVideoConfigs.
-    class VideoStreamFactory
-        : public VideoEncoderConfig::VideoStreamFactoryInterface {
-     public:
-      VideoStreamFactory() {}
-
-     private:
-      std::vector<VideoStream> CreateEncoderStreams(
-          int width,
-          int height,
-          const VideoEncoderConfig& encoder_config) override {
-        std::vector<VideoStream> streams =
-            test::CreateVideoStreams(width, height, encoder_config);
-        // Set low simulcast bitrates to not have to wait for bandwidth ramp-up.
-        for (size_t i = 0; i < encoder_config.number_of_streams; ++i) {
-          streams[i].min_bitrate_bps = 10000;
-          streams[i].target_bitrate_bps = 15000;
-          streams[i].max_bitrate_bps = 20000;
-        }
-        return streams;
-      }
-    };
-
     void ModifyVideoConfigs(
         VideoSendStream::Config* send_config,
         std::vector<VideoReceiveStream::Config>* receive_configs,
         VideoEncoderConfig* encoder_config) override {
-      encoder_config->video_stream_factory =
-          new rtc::RefCountedObject<VideoStreamFactory>();
+      if (num_ssrcs_ > 1) {
+        // Set low simulcast bitrates to not have to wait for bandwidth ramp-up.
+        for (size_t i = 0; i < encoder_config->streams.size(); ++i) {
+          encoder_config->streams[i].min_bitrate_bps = 10000;
+          encoder_config->streams[i].target_bitrate_bps = 15000;
+          encoder_config->streams[i].max_bitrate_bps = 20000;
+        }
+      }
+
       video_encoder_config_all_streams_ = encoder_config->Copy();
       if (send_single_ssrc_first_)
-        encoder_config->number_of_streams = 1;
+        encoder_config->streams.resize(1);
     }
 
     void OnVideoStreamsCreated(
@@ -2557,7 +2559,7 @@
         std::vector<VideoReceiveStream::Config>* receive_configs,
         VideoEncoderConfig* encoder_config) override {
       send_config->encoder_settings.encoder = this;
-      RTC_DCHECK_EQ(1u, encoder_config->number_of_streams);
+      RTC_DCHECK_EQ(1u, encoder_config->streams.size());
     }
 
     int32_t SetRates(uint32_t new_target_bitrate, uint32_t framerate) override {
@@ -2829,38 +2831,16 @@
       return config;
     }
 
-    // This test use other VideoStream settings than the the default settings
-    // implemented in DefaultVideoStreamFactory. Therefore  this test implement
-    // its own VideoEncoderConfig::VideoStreamFactoryInterface which is created
-    // in ModifyVideoConfigs.
-    class VideoStreamFactory
-        : public VideoEncoderConfig::VideoStreamFactoryInterface {
-     public:
-      VideoStreamFactory() {}
-
-     private:
-      std::vector<VideoStream> CreateEncoderStreams(
-          int width,
-          int height,
-          const VideoEncoderConfig& encoder_config) override {
-        std::vector<VideoStream> streams =
-            test::CreateVideoStreams(width, height, encoder_config);
-        // Set low simulcast bitrates to not have to wait for bandwidth ramp-up.
-        for (size_t i = 0; i < encoder_config.number_of_streams; ++i) {
-          streams[i].min_bitrate_bps = 10000;
-          streams[i].target_bitrate_bps = 15000;
-          streams[i].max_bitrate_bps = 20000;
-        }
-        return streams;
-      }
-    };
-
     void ModifyVideoConfigs(
         VideoSendStream::Config* send_config,
         std::vector<VideoReceiveStream::Config>* receive_configs,
         VideoEncoderConfig* encoder_config) override {
-      encoder_config->video_stream_factory =
-          new rtc::RefCountedObject<VideoStreamFactory>();
+      // Set low rates to avoid waiting for rampup.
+      for (size_t i = 0; i < encoder_config->streams.size(); ++i) {
+        encoder_config->streams[i].min_bitrate_bps = 10000;
+        encoder_config->streams[i].target_bitrate_bps = 15000;
+        encoder_config->streams[i].max_bitrate_bps = 20000;
+      }
       send_config->pre_encode_callback = this;  // Used to inject delay.
       expected_cname_ = send_config->rtp.c_name = "SomeCName";
 
@@ -3053,39 +3033,17 @@
 
     size_t GetNumVideoStreams() const override { return kNumSsrcs; }
 
-    // This test use other VideoStream settings than the the default settings
-    // implemented in DefaultVideoStreamFactory. Therefore  this test implement
-    // its own VideoEncoderConfig::VideoStreamFactoryInterface which is created
-    // in ModifyVideoConfigs.
-    class VideoStreamFactory
-        : public VideoEncoderConfig::VideoStreamFactoryInterface {
-     public:
-      VideoStreamFactory() {}
-
-     private:
-      std::vector<VideoStream> CreateEncoderStreams(
-          int width,
-          int height,
-          const VideoEncoderConfig& encoder_config) override {
-        std::vector<VideoStream> streams =
-            test::CreateVideoStreams(width, height, encoder_config);
-        // Set low simulcast bitrates to not have to wait for bandwidth ramp-up.
-        for (size_t i = 0; i < encoder_config.number_of_streams; ++i) {
-          streams[i].min_bitrate_bps = 10000;
-          streams[i].target_bitrate_bps = 15000;
-          streams[i].max_bitrate_bps = 20000;
-        }
-        return streams;
-      }
-    };
-
     void ModifyVideoConfigs(
         VideoSendStream::Config* send_config,
         std::vector<VideoReceiveStream::Config>* receive_configs,
         VideoEncoderConfig* encoder_config) override {
       // Set low simulcast bitrates to not have to wait for bandwidth ramp-up.
-      encoder_config->video_stream_factory =
-          new rtc::RefCountedObject<VideoStreamFactory>();
+      for (size_t i = 0; i < encoder_config->streams.size(); ++i) {
+        encoder_config->streams[i].min_bitrate_bps = 10000;
+        encoder_config->streams[i].target_bitrate_bps = 15000;
+        encoder_config->streams[i].max_bitrate_bps = 20000;
+      }
+
       send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
 
       for (size_t i = 0; i < kNumSsrcs; ++i)
@@ -3112,43 +3070,6 @@
 
 void EndToEndTest::TestRtpStatePreservation(bool use_rtx,
                                             bool provoke_rtcpsr_before_rtp) {
-  // This test use other VideoStream settings than the the default settings
-  // implemented in DefaultVideoStreamFactory. Therefore  this test implement
-  // its own VideoEncoderConfig::VideoStreamFactoryInterface which is created
-  // in ModifyVideoConfigs.
-  class VideoStreamFactory
-      : public VideoEncoderConfig::VideoStreamFactoryInterface {
-   public:
-    VideoStreamFactory() {}
-
-   private:
-    std::vector<VideoStream> CreateEncoderStreams(
-        int width,
-        int height,
-        const VideoEncoderConfig& encoder_config) override {
-      std::vector<VideoStream> streams =
-          test::CreateVideoStreams(width, height, encoder_config);
-
-      if (encoder_config.number_of_streams > 1) {
-        // Lower bitrates so that all streams send initially.
-        RTC_DCHECK_EQ(3u, encoder_config.number_of_streams);
-        for (size_t i = 0; i < encoder_config.number_of_streams; ++i) {
-          streams[i].min_bitrate_bps = 10000;
-          streams[i].target_bitrate_bps = 15000;
-          streams[i].max_bitrate_bps = 20000;
-        }
-      } else {
-        // Use the same total bitrates when sending a single stream to avoid
-        // lowering
-        // the bitrate estimate and requiring a subsequent rampup.
-        streams[0].min_bitrate_bps = 3 * 10000;
-        streams[0].target_bitrate_bps = 3 * 15000;
-        streams[0].max_bitrate_bps = 3 * 20000;
-      }
-      return streams;
-    }
-  };
-
   class RtpSequenceObserver : public test::RtpRtcpObserver {
    public:
     explicit RtpSequenceObserver(bool use_rtx)
@@ -3284,17 +3205,30 @@
     video_send_config_.rtp.rtx.payload_type = kSendRtxPayloadType;
   }
 
-  video_encoder_config_.video_stream_factory =
-      new rtc::RefCountedObject<VideoStreamFactory>();
+  // Lower bitrates so that all streams send initially.
+  for (size_t i = 0; i < video_encoder_config_.streams.size(); ++i) {
+    video_encoder_config_.streams[i].min_bitrate_bps = 10000;
+    video_encoder_config_.streams[i].target_bitrate_bps = 15000;
+    video_encoder_config_.streams[i].max_bitrate_bps = 20000;
+  }
+
   // Use the same total bitrates when sending a single stream to avoid lowering
   // the bitrate estimate and requiring a subsequent rampup.
   VideoEncoderConfig one_stream = video_encoder_config_.Copy();
-  // one_stream.streams.resize(1);
-  one_stream.number_of_streams = 1;
+  one_stream.streams.resize(1);
+  for (size_t i = 1; i < video_encoder_config_.streams.size(); ++i) {
+    one_stream.streams.front().min_bitrate_bps +=
+        video_encoder_config_.streams[i].min_bitrate_bps;
+    one_stream.streams.front().target_bitrate_bps +=
+        video_encoder_config_.streams[i].target_bitrate_bps;
+    one_stream.streams.front().max_bitrate_bps +=
+        video_encoder_config_.streams[i].max_bitrate_bps;
+  }
+
   CreateMatchingReceiveConfigs(&receive_transport);
 
   CreateVideoStreams();
-  CreateFrameGeneratorCapturer(30, 1280, 720);
+  CreateFrameGeneratorCapturer();
 
   Start();
   EXPECT_TRUE(observer.Wait())
@@ -3319,7 +3253,7 @@
       static_cast<webrtc::test::DirectTransport&>(receive_transport)
           .SendRtcp(packet.data(), packet.size());
     }
-    CreateFrameGeneratorCapturer(30, 1280, 720);
+    CreateFrameGeneratorCapturer();
     frame_generator_capturer_->Start();
 
     observer.ResetExpectedSsrcs(1);
@@ -3574,8 +3508,7 @@
   CreateMatchingReceiveConfigs(&receiver_transport);
 
   CreateVideoStreams();
-  CreateFrameGeneratorCapturer(kDefaultFramerate, kDefaultWidth,
-                               kDefaultHeight);
+  CreateFrameGeneratorCapturer();
   Start();
 
   int64_t start_time_ms = clock_->TimeInMilliseconds();
@@ -3608,8 +3541,7 @@
   CreateSendConfig(1, 0, transport);
   video_send_config_.encoder_settings.encoder = encoder;
   CreateVideoStreams();
-  CreateFrameGeneratorCapturer(kDefaultFramerate, kDefaultWidth,
-                               kDefaultHeight);
+  CreateFrameGeneratorCapturer();
 
   Start();
   SleepMs(kSilenceTimeoutMs);
@@ -3630,8 +3562,7 @@
   CreateSendConfig(1, 0, &sender_transport);
   CreateMatchingReceiveConfigs(transport);
   CreateVideoStreams();
-  CreateFrameGeneratorCapturer(kDefaultFramerate, kDefaultWidth,
-                               kDefaultHeight);
+  CreateFrameGeneratorCapturer();
 
   Start();
   SleepMs(kSilenceTimeoutMs);
diff --git a/webrtc/video/video_quality_test.cc b/webrtc/video/video_quality_test.cc
index 68e353c..6186aaf 100644
--- a/webrtc/video/video_quality_test.cc
+++ b/webrtc/video/video_quality_test.cc
@@ -29,7 +29,6 @@
 #include "webrtc/modules/rtp_rtcp/include/rtp_header_parser.h"
 #include "webrtc/modules/rtp_rtcp/source/rtp_utility.h"
 #include "webrtc/system_wrappers/include/cpu_info.h"
-#include "webrtc/test/encoder_settings.h"
 #include "webrtc/test/layer_filtering_transport.h"
 #include "webrtc/test/run_loop.h"
 #include "webrtc/test/statistics.h"
@@ -1015,8 +1014,7 @@
 
   video_encoder_config_.min_transmit_bitrate_bps =
       params_.common.min_transmit_bps;
-  test::FillEncoderConfiguration(params_.ss.streams.size(),
-                                 &video_encoder_config_);
+  video_encoder_config_.streams = params_.ss.streams;
   video_encoder_config_.spatial_layers = params_.ss.spatial_layers;
 
   CreateMatchingReceiveConfigs(recv_transport);
diff --git a/webrtc/video/video_send_stream.cc b/webrtc/video/video_send_stream.cc
index 2a72737..259e828 100644
--- a/webrtc/video/video_send_stream.cc
+++ b/webrtc/video/video_send_stream.cc
@@ -521,11 +521,18 @@
                      config_.pre_encode_callback, config_.overuse_callback,
                      config_.post_encode_callback));
 
+  // TODO(perkj): Remove vector<VideoStreams> from VideoEncoderConfig and
+  // replace with max_bitrate. The VideoStream should be created by ViEEncoder
+  // when the video resolution is known.
+  int initial_max_encoder_bitrate = 0;
+  for (const auto& stream : encoder_config.streams)
+    initial_max_encoder_bitrate += stream.max_bitrate_bps;
+
   worker_queue_->PostTask(std::unique_ptr<rtc::QueuedTask>(new ConstructionTask(
       &send_stream_, &thread_sync_event_, &stats_proxy_, vie_encoder_.get(),
       module_process_thread, call_stats, congestion_controller,
       bitrate_allocator, send_delay_stats, remb, event_log, &config_,
-      encoder_config.max_bitrate_bps, suspended_ssrcs)));
+      initial_max_encoder_bitrate, suspended_ssrcs)));
 
   // Wait for ConstructionTask to complete so that |send_stream_| can be used.
   // |module_process_thread| must be registered and deregistered on the thread
@@ -572,9 +579,12 @@
 }
 
 void VideoSendStream::ReconfigureVideoEncoder(VideoEncoderConfig config) {
-  // TODO(perkj): Some test cases in VideoSendStreamTest call
-  // ReconfigureVideoEncoder from the network thread.
-  // RTC_DCHECK_RUN_ON(&thread_checker_);
+  // ReconfigureVideoEncoder will be called on the thread that deliverers video
+  // frames. We must change the encoder settings immediately so that
+  // the codec settings matches the next frame.
+  // TODO(perkj): Move logic for reconfiguration the encoder due to frame size
+  // change from WebRtcVideoChannel2::WebRtcVideoSendStream::OnFrame to
+  // be internally handled by ViEEncoder.
   vie_encoder_->ConfigureEncoder(std::move(config),
                                  config_.rtp.max_packet_size);
 }
diff --git a/webrtc/video/video_send_stream_tests.cc b/webrtc/video/video_send_stream_tests.cc
index d7d206f..656aadc 100644
--- a/webrtc/video/video_send_stream_tests.cc
+++ b/webrtc/video/video_send_stream_tests.cc
@@ -37,7 +37,6 @@
 #include "webrtc/test/frame_utils.h"
 #include "webrtc/test/null_transport.h"
 #include "webrtc/test/testsupport/perf_test.h"
-
 #include "webrtc/video/send_statistics_proxy.h"
 #include "webrtc/video_frame.h"
 #include "webrtc/video_send_stream.h"
@@ -909,18 +908,16 @@
         VideoSendStream::Config* send_config,
         std::vector<VideoReceiveStream::Config>* receive_configs,
         VideoEncoderConfig* encoder_config) override {
-      RTC_DCHECK_EQ(1u, encoder_config->number_of_streams);
       transport_adapter_.reset(
           new internal::TransportAdapter(send_config->send_transport));
       transport_adapter_->Enable();
       send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
       send_config->pre_encode_callback = this;
       send_config->suspend_below_min_bitrate = true;
-      int min_bitrate_bps =
-          test::DefaultVideoStreamFactory::kDefaultMinBitratePerStream[0];
+      int min_bitrate_bps = encoder_config->streams[0].min_bitrate_bps;
       set_low_remb_bps(min_bitrate_bps - 10000);
       int threshold_window = std::max(min_bitrate_bps / 10, 20000);
-      ASSERT_GT(encoder_config->max_bitrate_bps,
+      ASSERT_GT(encoder_config->streams[0].max_bitrate_bps,
                 min_bitrate_bps + threshold_window + 5000);
       set_high_remb_bps(min_bitrate_bps + threshold_window + 5000);
     }
@@ -1209,7 +1206,7 @@
       VideoSendStream::Config* send_config,
       std::vector<VideoReceiveStream::Config>* receive_configs,
       VideoEncoderConfig* encoder_config) override {
-    RTC_DCHECK_EQ(1u, encoder_config->number_of_streams);
+    RTC_DCHECK_EQ(1u, encoder_config->streams.size());
     if (running_without_padding_) {
       encoder_config->min_transmit_bitrate_bps = 0;
       encoder_config->content_type =
@@ -1277,84 +1274,6 @@
   RunBaseTest(&test);
 }
 
-// This test verifies that new frame sizes reconfigures encoders even though not
-// (yet) sending. The purpose of this is to permit encoding as quickly as
-// possible once we start sending. Likely the frames being input are from the
-// same source that will be sent later, which just means that we're ready
-// earlier.
-TEST_F(VideoSendStreamTest,
-       EncoderReconfigureOnResolutionChangeWhenNotSending) {
-  class EncoderObserver : public test::FakeEncoder {
-   public:
-    EncoderObserver()
-        : FakeEncoder(Clock::GetRealTimeClock()),
-          init_encode_called_(false, false),
-          number_of_initializations_(0),
-          last_initialized_frame_width_(0),
-          last_initialized_frame_height_(0) {}
-
-    void WaitForResolution(int width, int height) {
-      {
-        rtc::CritScope lock(&crit_);
-        if (last_initialized_frame_width_ == width &&
-            last_initialized_frame_height_ == height) {
-          return;
-        }
-      }
-      init_encode_called_.Wait(VideoSendStreamTest::kDefaultTimeoutMs);
-      {
-        rtc::CritScope lock(&crit_);
-        EXPECT_EQ(width, last_initialized_frame_width_);
-        EXPECT_EQ(height, last_initialized_frame_height_);
-      }
-    }
-
-   private:
-    int32_t InitEncode(const VideoCodec* config,
-                       int32_t number_of_cores,
-                       size_t max_payload_size) override {
-      rtc::CritScope lock(&crit_);
-      last_initialized_frame_width_ = config->width;
-      last_initialized_frame_height_ = config->height;
-      ++number_of_initializations_;
-      // First time InitEncode is called, the frame size is unknown.
-      if (number_of_initializations_ > 1)
-        init_encode_called_.Set();
-      return FakeEncoder::InitEncode(config, number_of_cores, max_payload_size);
-    }
-
-    int32_t Encode(const VideoFrame& input_image,
-                   const CodecSpecificInfo* codec_specific_info,
-                   const std::vector<FrameType>* frame_types) override {
-      ADD_FAILURE()
-          << "Unexpected Encode call since the send stream is not started";
-      return 0;
-    }
-
-    rtc::CriticalSection crit_;
-    rtc::Event init_encode_called_;
-    size_t number_of_initializations_ GUARDED_BY(&crit_);
-    int last_initialized_frame_width_ GUARDED_BY(&crit_);
-    int last_initialized_frame_height_ GUARDED_BY(&crit_);
-  };
-
-  CreateSenderCall(Call::Config());
-  test::NullTransport transport;
-  CreateSendConfig(1, 0, &transport);
-  EncoderObserver encoder;
-  video_send_config_.encoder_settings.encoder = &encoder;
-  CreateVideoStreams();
-  CreateFrameGeneratorCapturer(kDefaultFramerate, kDefaultWidth,
-                               kDefaultHeight);
-  frame_generator_capturer_->Start();
-
-  encoder.WaitForResolution(kDefaultWidth, kDefaultHeight);
-  frame_generator_capturer_->ChangeResolution(kDefaultWidth * 2,
-                                              kDefaultHeight * 2);
-  encoder.WaitForResolution(kDefaultWidth * 2, kDefaultHeight * 2);
-  DestroyStreams();
-}
-
 TEST_F(VideoSendStreamTest, CanReconfigureToUseStartBitrateAbovePreviousMax) {
   class StartBitrateObserver : public test::FakeEncoder {
    public:
@@ -1400,22 +1319,21 @@
   CreateSendConfig(1, 0, &transport);
 
   Call::Config::BitrateConfig bitrate_config;
-  bitrate_config.start_bitrate_bps = 2 * video_encoder_config_.max_bitrate_bps;
+  bitrate_config.start_bitrate_bps =
+      2 * video_encoder_config_.streams[0].max_bitrate_bps;
   sender_call_->SetBitrateConfig(bitrate_config);
 
   StartBitrateObserver encoder;
   video_send_config_.encoder_settings.encoder = &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;
 
   CreateVideoStreams();
 
   EXPECT_TRUE(encoder.WaitForStartBitrate());
-  EXPECT_EQ(video_encoder_config_.max_bitrate_bps / 1000,
+  EXPECT_EQ(video_encoder_config_.streams[0].max_bitrate_bps / 1000,
             encoder.GetStartBitrateKbps());
 
-  video_encoder_config_.max_bitrate_bps = 2 * bitrate_config.start_bitrate_bps;
+  video_encoder_config_.streams[0].max_bitrate_bps =
+      2 * bitrate_config.start_bitrate_bps;
   video_send_stream_->ReconfigureVideoEncoder(video_encoder_config_.Copy());
 
   // New bitrate should be reconfigured above the previous max. As there's no
@@ -1541,9 +1459,8 @@
   // Prepare five input frames. Send ordinary VideoFrame and texture frames
   // alternatively.
   std::vector<VideoFrame> input_frames;
-  int width = 168;
-  int height = 132;
-
+  int width = static_cast<int>(video_encoder_config_.streams[0].width);
+  int height = static_cast<int>(video_encoder_config_.streams[0].height);
   test::FakeNativeHandle* handle1 = new test::FakeNativeHandle();
   test::FakeNativeHandle* handle2 = new test::FakeNativeHandle();
   test::FakeNativeHandle* handle3 = new test::FakeNativeHandle();
@@ -1561,6 +1478,9 @@
   video_send_stream_->SetSource(&forwarder);
   for (size_t i = 0; i < input_frames.size(); i++) {
     forwarder.IncomingCapturedFrame(input_frames[i]);
+    // Do not send the next frame too fast, so the frame dropper won't drop it.
+    if (i < input_frames.size() - 1)
+      SleepMs(1000 / video_encoder_config_.streams[0].max_framerate);
     // Wait until the output frame is received before sending the next input
     // frame. Or the previous input frame may be replaced without delivering.
     observer.WaitOutputFrame();
@@ -1687,12 +1607,9 @@
 
     void PerformTest() override {
       EXPECT_TRUE(Wait()) << "Timed out while waiting for Encode.";
-      // Expect  |num_releases| == 1 since the encoder has been reconfigured
-      // once when the first frame is encoded. Not until at that point is the
-      // frame size known and the encoder can be properly initialized.
-      EXPECT_EQ(1u, num_releases());
+      EXPECT_EQ(0u, num_releases());
       stream_->ReconfigureVideoEncoder(std::move(encoder_config_));
-      EXPECT_EQ(1u, num_releases());
+      EXPECT_EQ(0u, num_releases());
       stream_->Stop();
       // Encoder should not be released before destroying the VideoSendStream.
       EXPECT_FALSE(IsReleased());
@@ -1714,7 +1631,7 @@
   RunBaseTest(&test_encoder);
 
   EXPECT_TRUE(test_encoder.IsReleased());
-  EXPECT_EQ(2u, test_encoder.num_releases());
+  EXPECT_EQ(1u, test_encoder.num_releases());
 }
 
 TEST_F(VideoSendStreamTest, EncoderSetupPropagatesCommonEncoderConfigValues) {
@@ -1797,26 +1714,6 @@
   }
 
  private:
-  class VideoStreamFactory
-      : public VideoEncoderConfig::VideoStreamFactoryInterface {
-   public:
-    VideoStreamFactory() {}
-
-   private:
-    std::vector<VideoStream> CreateEncoderStreams(
-        int width,
-        int height,
-        const VideoEncoderConfig& encoder_config) override {
-      std::vector<VideoStream> streams =
-          test::CreateVideoStreams(width, height, encoder_config);
-      for (size_t i = 0; i < streams.size(); ++i) {
-        streams[i].temporal_layer_thresholds_bps.resize(
-            kVideoCodecConfigObserverNumberOfTemporalLayers - 1);
-      }
-      return streams;
-    }
-  };
-
   void ModifyVideoConfigs(
       VideoSendStream::Config* send_config,
       std::vector<VideoReceiveStream::Config>* receive_configs,
@@ -1824,9 +1721,12 @@
     send_config->encoder_settings.encoder = this;
     send_config->encoder_settings.payload_name = codec_name_;
 
+    for (size_t i = 0; i < encoder_config->streams.size(); ++i) {
+      encoder_config->streams[i].temporal_layer_thresholds_bps.resize(
+          kVideoCodecConfigObserverNumberOfTemporalLayers - 1);
+    }
+
     encoder_config->encoder_specific_settings = GetEncoderSpecificSettings();
-    encoder_config->video_stream_factory =
-        new rtc::RefCountedObject<VideoStreamFactory>();
     encoder_config_ = encoder_config->Copy();
   }
 
@@ -2022,26 +1922,6 @@
 
 TEST_F(VideoSendStreamTest, TranslatesTwoLayerScreencastToTargetBitrate) {
   static const int kScreencastTargetBitrateKbps = 200;
-
-  class VideoStreamFactory
-      : public VideoEncoderConfig::VideoStreamFactoryInterface {
-   public:
-    VideoStreamFactory() {}
-
-   private:
-    std::vector<VideoStream> CreateEncoderStreams(
-        int width,
-        int height,
-        const VideoEncoderConfig& encoder_config) override {
-      std::vector<VideoStream> streams =
-          test::CreateVideoStreams(width, height, encoder_config);
-      EXPECT_TRUE(streams[0].temporal_layer_thresholds_bps.empty());
-      streams[0].temporal_layer_thresholds_bps.push_back(
-          kScreencastTargetBitrateKbps * 1000);
-      return streams;
-    }
-  };
-
   class ScreencastTargetBitrateTest : public test::SendTest,
                                       public test::FakeEncoder {
    public:
@@ -2064,9 +1944,11 @@
         std::vector<VideoReceiveStream::Config>* receive_configs,
         VideoEncoderConfig* encoder_config) override {
       send_config->encoder_settings.encoder = this;
-      EXPECT_EQ(1u, encoder_config->number_of_streams);
-      encoder_config->video_stream_factory =
-          new rtc::RefCountedObject<VideoStreamFactory>();
+      EXPECT_EQ(1u, encoder_config->streams.size());
+      EXPECT_TRUE(
+          encoder_config->streams[0].temporal_layer_thresholds_bps.empty());
+      encoder_config->streams[0].temporal_layer_thresholds_bps.push_back(
+          kScreencastTargetBitrateKbps * 1000);
       encoder_config->content_type = VideoEncoderConfig::ContentType::kScreen;
     }
 
@@ -2107,8 +1989,7 @@
                        size_t maxPayloadSize) override {
       EXPECT_GE(codecSettings->startBitrate, codecSettings->minBitrate);
       EXPECT_LE(codecSettings->startBitrate, codecSettings->maxBitrate);
-      // First reinitialization happens due to that the frame size is updated.
-      if (num_initializations_ == 0 || num_initializations_ == 1) {
+      if (num_initializations_ == 0) {
         EXPECT_EQ(static_cast<unsigned int>(kMinBitrateKbps),
                   codecSettings->minBitrate);
         EXPECT_EQ(static_cast<unsigned int>(kStartBitrateKbps),
@@ -2116,14 +1997,14 @@
         EXPECT_EQ(static_cast<unsigned int>(kMaxBitrateKbps),
                   codecSettings->maxBitrate);
         observation_complete_.Set();
-      } else if (num_initializations_ == 2) {
+      } else if (num_initializations_ == 1) {
         EXPECT_EQ(static_cast<unsigned int>(kLowerMaxBitrateKbps),
                   codecSettings->maxBitrate);
         // The start bitrate should be kept (-1) and capped to the max bitrate.
         // Since this is not an end-to-end call no receiver should have been
         // returning a REMB that could lower this estimate.
         EXPECT_EQ(codecSettings->startBitrate, codecSettings->maxBitrate);
-      } else if (num_initializations_ == 3) {
+      } else if (num_initializations_ == 2) {
         EXPECT_EQ(static_cast<unsigned int>(kIncreasedMaxBitrateKbps),
                   codecSettings->maxBitrate);
         // The start bitrate will be whatever the rate BitRateController
@@ -2131,9 +2012,7 @@
         // bitrate.
       }
       ++num_initializations_;
-      if (num_initializations_ > 1) {
-        init_encode_event_.Set();
-      }
+      init_encode_event_.Set();
       return FakeEncoder::InitEncode(codecSettings, numberOfCores,
                                      maxPayloadSize);
     }
@@ -2141,9 +2020,6 @@
     int32_t SetRates(uint32_t newBitRate, uint32_t frameRate) override {
       {
         rtc::CritScope lock(&crit_);
-        if (target_bitrate_ == newBitRate) {
-          return FakeEncoder::SetRates(newBitRate, frameRate);
-        }
         target_bitrate_ = newBitRate;
       }
       bitrate_changed_event_.Set();
@@ -2166,26 +2042,6 @@
       return config;
     }
 
-    class VideoStreamFactory
-        : public VideoEncoderConfig::VideoStreamFactoryInterface {
-     public:
-      explicit VideoStreamFactory(int min_bitrate_bps)
-          : min_bitrate_bps_(min_bitrate_bps) {}
-
-     private:
-      std::vector<VideoStream> CreateEncoderStreams(
-          int width,
-          int height,
-          const VideoEncoderConfig& encoder_config) override {
-        std::vector<VideoStream> streams =
-            test::CreateVideoStreams(width, height, encoder_config);
-        streams[0].min_bitrate_bps = min_bitrate_bps_;
-        return streams;
-      }
-
-      const int min_bitrate_bps_;
-    };
-
     void ModifyVideoConfigs(
         VideoSendStream::Config* send_config,
         std::vector<VideoReceiveStream::Config>* receive_configs,
@@ -2193,11 +2049,8 @@
       send_config->encoder_settings.encoder = this;
       // Set bitrates lower/higher than min/max to make sure they are properly
       // capped.
-      encoder_config->max_bitrate_bps = kMaxBitrateKbps * 1000;
-      // Create a new StreamFactory to be able to set
-      // |VideoStream.min_bitrate_bps|.
-      encoder_config->video_stream_factory =
-          new rtc::RefCountedObject<VideoStreamFactory>(kMinBitrateKbps * 1000);
+      encoder_config->streams.front().min_bitrate_bps = kMinBitrateKbps * 1000;
+      encoder_config->streams.front().max_bitrate_bps = kMaxBitrateKbps * 1000;
       encoder_config_ = encoder_config->Copy();
     }
 
@@ -2222,20 +2075,25 @@
       call_->SetBitrateConfig(bitrate_config);
       // Encoder rate is capped by EncoderConfig max_bitrate_bps.
       WaitForSetRates(kMaxBitrateKbps);
-      encoder_config_.max_bitrate_bps = kLowerMaxBitrateKbps * 1000;
+
+      encoder_config_.streams[0].min_bitrate_bps = 0;
+      encoder_config_.streams[0].max_bitrate_bps = kLowerMaxBitrateKbps * 1000;
+      send_stream_->ReconfigureVideoEncoder(encoder_config_.Copy());
+      ASSERT_TRUE(
+          init_encode_event_.Wait(VideoSendStreamTest::kDefaultTimeoutMs));
+      EXPECT_EQ(2, num_initializations_)
+          << "Encoder should have been reconfigured with the new value.";
+      WaitForSetRates(kLowerMaxBitrateKbps);
+
+      encoder_config_.streams[0].target_bitrate_bps =
+          encoder_config_.streams[0].min_bitrate_bps;
+      encoder_config_.streams[0].max_bitrate_bps =
+          kIncreasedMaxBitrateKbps * 1000;
       send_stream_->ReconfigureVideoEncoder(encoder_config_.Copy());
       ASSERT_TRUE(
           init_encode_event_.Wait(VideoSendStreamTest::kDefaultTimeoutMs));
       EXPECT_EQ(3, num_initializations_)
           << "Encoder should have been reconfigured with the new value.";
-      WaitForSetRates(kLowerMaxBitrateKbps);
-
-      encoder_config_.max_bitrate_bps = kIncreasedMaxBitrateKbps * 1000;
-      send_stream_->ReconfigureVideoEncoder(encoder_config_.Copy());
-      ASSERT_TRUE(
-          init_encode_event_.Wait(VideoSendStreamTest::kDefaultTimeoutMs));
-      EXPECT_EQ(4, num_initializations_)
-          << "Encoder should have been reconfigured with the new value.";
       // Expected target bitrate is the start bitrate set in the call to
       // call_->SetBitrateConfig.
       WaitForSetRates(kIncreasedStartBitrateKbps);
@@ -2245,7 +2103,6 @@
     rtc::Event bitrate_changed_event_;
     rtc::CriticalSection crit_;
     uint32_t target_bitrate_ GUARDED_BY(&crit_);
-
     int num_initializations_;
     webrtc::Call* call_;
     webrtc::VideoSendStream* send_stream_;
@@ -2301,7 +2158,7 @@
         std::vector<VideoReceiveStream::Config>* receive_configs,
         VideoEncoderConfig* encoder_config) override {
       send_config->encoder_settings.encoder = this;
-      EXPECT_EQ(kNumStreams, encoder_config->number_of_streams);
+      EXPECT_EQ(kNumStreams, encoder_config->streams.size());
     }
 
     size_t GetNumVideoStreams() const override { return kNumStreams; }
@@ -2343,9 +2200,7 @@
         vp9_encoder_(VP9Encoder::Create()),
         vp9_settings_(VideoEncoder::GetDefaultVp9Settings()),
         packets_sent_(0),
-        frames_sent_(0),
-        expected_width_(0),
-        expected_height_(0) {}
+        frames_sent_(0) {}
 
   virtual void ModifyVideoConfigsHook(
       VideoSendStream::Config* send_config,
@@ -2357,27 +2212,6 @@
  private:
   const int kVp9PayloadType = 105;
 
-  class VideoStreamFactory
-      : public VideoEncoderConfig::VideoStreamFactoryInterface {
-   public:
-    explicit VideoStreamFactory(size_t number_of_temporal_layers)
-        : number_of_temporal_layers_(number_of_temporal_layers) {}
-
-   private:
-    std::vector<VideoStream> CreateEncoderStreams(
-        int width,
-        int height,
-        const VideoEncoderConfig& encoder_config) override {
-      std::vector<VideoStream> streams =
-          test::CreateVideoStreams(width, height, encoder_config);
-      streams[0].temporal_layer_thresholds_bps.resize(
-          number_of_temporal_layers_ - 1);
-      return streams;
-    }
-
-    const size_t number_of_temporal_layers_;
-  };
-
   void ModifyVideoConfigs(
       VideoSendStream::Config* send_config,
       std::vector<VideoReceiveStream::Config>* receive_configs,
@@ -2388,20 +2222,12 @@
     ModifyVideoConfigsHook(send_config, receive_configs, encoder_config);
     encoder_config->encoder_specific_settings = new rtc::RefCountedObject<
       VideoEncoderConfig::Vp9EncoderSpecificSettings>(vp9_settings_);
-    EXPECT_EQ(1u, encoder_config->number_of_streams);
-    encoder_config->video_stream_factory =
-        new rtc::RefCountedObject<VideoStreamFactory>(
-            vp9_settings_.numberOfTemporalLayers);
+    EXPECT_EQ(1u, encoder_config->streams.size());
+    encoder_config->streams[0].temporal_layer_thresholds_bps.resize(
+        vp9_settings_.numberOfTemporalLayers - 1);
     encoder_config_ = encoder_config->Copy();
   }
 
-  void ModifyVideoCaptureStartResolution(int* width,
-                                         int* height,
-                                         int* frame_rate) override {
-    expected_width_ = *width;
-    expected_height_ = *height;
-  }
-
   void PerformTest() override {
     EXPECT_TRUE(Wait()) << "Test timed out waiting for VP9 packet, num frames "
                         << frames_sent_;
@@ -2591,8 +2417,8 @@
     EXPECT_EQ(vp9_settings_.numberOfSpatialLayers,  // N_S + 1
               vp9.num_spatial_layers);
     EXPECT_TRUE(vp9.spatial_layer_resolution_present);  // Y:1
-    int expected_width = expected_width_;
-    int expected_height = expected_height_;
+    size_t expected_width = encoder_config_.streams[0].width;
+    size_t expected_height = encoder_config_.streams[0].height;
     for (int i = static_cast<int>(vp9.num_spatial_layers) - 1; i >= 0; --i) {
       EXPECT_EQ(expected_width, vp9.width[i]);    // WIDTH
       EXPECT_EQ(expected_height, vp9.height[i]);  // HEIGHT
@@ -2636,8 +2462,6 @@
   RTPVideoHeaderVP9 last_vp9_;
   size_t packets_sent_;
   size_t frames_sent_;
-  int expected_width_;
-  int expected_height_;
 };
 
 TEST_F(VideoSendStreamTest, Vp9NonFlexMode_1Tl1SLayers) {
@@ -2739,22 +2563,15 @@
       vp9_settings_.numberOfTemporalLayers = 1;
       vp9_settings_.numberOfSpatialLayers = 1;
 
-      EXPECT_EQ(1u, encoder_config->number_of_streams);
+      EXPECT_EQ(1u, encoder_config->streams.size());
+      encoder_config->streams[0].width = kWidth;
+      encoder_config->streams[0].height = kHeight;
     }
 
     void InspectHeader(const RTPVideoHeaderVP9& vp9_header) override {
       if (frames_sent_ > kNumFramesToSend)
         observation_complete_.Set();
     }
-
-    void ModifyVideoCaptureStartResolution(int* width,
-                                           int* height,
-                                           int* frame_rate) override {
-      expected_width_ = kWidth;
-      expected_height_ = kHeight;
-      *width = kWidth;
-      *height = kHeight;
-    }
   } test;
 
   RunBaseTest(&test);
diff --git a/webrtc/video/vie_encoder.cc b/webrtc/video/vie_encoder.cc
index 95a6f5a..8c3ca04 100644
--- a/webrtc/video/vie_encoder.cc
+++ b/webrtc/video/vie_encoder.cc
@@ -41,11 +41,10 @@
   return kVideoCodecGeneric;
 }
 
-VideoCodec VideoEncoderConfigToVideoCodec(
-    const VideoEncoderConfig& config,
-    const std::vector<VideoStream>& streams,
-    const std::string& payload_name,
-    int payload_type) {
+VideoCodec VideoEncoderConfigToVideoCodec(const VideoEncoderConfig& config,
+                                          const std::string& payload_name,
+                                          int payload_type) {
+  const std::vector<VideoStream>& streams = config.streams;
   static const int kEncoderMinBitrateKbps = 30;
   RTC_DCHECK(!streams.empty());
   RTC_DCHECK_GE(config.min_transmit_bitrate_bps, 0);
@@ -60,10 +59,10 @@
       break;
     case VideoEncoderConfig::ContentType::kScreen:
       video_codec.mode = kScreensharing;
-      if (streams.size() == 1 &&
-          streams[0].temporal_layer_thresholds_bps.size() == 1) {
+      if (config.streams.size() == 1 &&
+          config.streams[0].temporal_layer_thresholds_bps.size() == 1) {
         video_codec.targetBitrate =
-            streams[0].temporal_layer_thresholds_bps[0] / 1000;
+            config.streams[0].temporal_layer_thresholds_bps[0] / 1000;
       }
       break;
   }
@@ -170,6 +169,8 @@
 
   RTC_DCHECK_GT(streams[0].max_framerate, 0);
   video_codec.maxFramerate = streams[0].max_framerate;
+  video_codec.expect_encode_from_texture = config.expect_encode_from_texture;
+
   return video_codec;
 }
 
@@ -305,6 +306,7 @@
       sink_(nullptr),
       settings_(settings),
       codec_type_(PayloadNameToCodecType(settings.payload_name)),
+      vp_(VideoProcessing::Create()),
       video_sender_(Clock::GetRealTimeClock(), this, this),
       overuse_detector_(Clock::GetRealTimeClock(),
                         GetCpuOveruseOptions(settings.full_overuse_time),
@@ -315,7 +317,7 @@
       stats_proxy_(stats_proxy),
       pre_encode_callback_(pre_encode_callback),
       module_process_thread_(nullptr),
-      pending_encoder_reconfiguration_(false),
+      encoder_config_(),
       encoder_start_bitrate_bps_(0),
       max_data_payload_length_(0),
       last_observed_bitrate_bps_(0),
@@ -332,6 +334,8 @@
       captured_frame_count_(0),
       dropped_frame_count_(0),
       encoder_queue_("EncoderQueue") {
+  vp_->EnableTemporalDecimation(false);
+
   encoder_queue_.PostTask([this, encoder_timing] {
     RTC_DCHECK_RUN_ON(&encoder_queue_);
     video_sender_.RegisterExternalEncoder(
@@ -403,62 +407,41 @@
                                              size_t max_data_payload_length) {
   RTC_DCHECK_RUN_ON(&encoder_queue_);
   RTC_DCHECK(sink_);
-  LOG(LS_INFO) << "ConfigureEncoder requested.";
+  LOG(LS_INFO) << "ConfigureEncoderOnTaskQueue";
 
   max_data_payload_length_ = max_data_payload_length;
   encoder_config_ = std::move(config);
-  pending_encoder_reconfiguration_ = true;
 
-  // Reconfigure the encoder now if the encoder has an internal source or
-  // if this is the first time the encoder is configured.
-  // Otherwise, the reconfiguration is deferred until the next frame to minimize
-  // the number of reconfigurations. The codec configuration depends on incoming
-  // video frame size.
-  if (!last_frame_info_ || settings_.internal_source) {
-    if (!last_frame_info_) {
-      last_frame_info_ = rtc::Optional<VideoFrameInfo>(
-          VideoFrameInfo(176, 144, kVideoRotation_0, false));
-    }
-    ReconfigureEncoder();
-  }
-}
+  VideoCodec video_codec = VideoEncoderConfigToVideoCodec(
+      encoder_config_, settings_.payload_name, settings_.payload_type);
 
-void ViEEncoder::ReconfigureEncoder() {
-  RTC_DCHECK_RUN_ON(&encoder_queue_);
-  RTC_DCHECK(pending_encoder_reconfiguration_);
-  std::vector<VideoStream> streams =
-      encoder_config_.video_stream_factory->CreateEncoderStreams(
-          last_frame_info_->width, last_frame_info_->height, encoder_config_);
+  // Setting target width and height for VPM.
+  RTC_CHECK_EQ(VPM_OK,
+               vp_->SetTargetResolution(video_codec.width, video_codec.height,
+                                        video_codec.maxFramerate));
 
-  VideoCodec codec = VideoEncoderConfigToVideoCodec(
-      encoder_config_, streams, settings_.payload_name, settings_.payload_type);
-
-  codec.startBitrate =
-      std::max(encoder_start_bitrate_bps_ / 1000, codec.minBitrate);
-  codec.startBitrate = std::min(codec.startBitrate, codec.maxBitrate);
-  codec.expect_encode_from_texture = last_frame_info_->is_texture;
+  video_codec.startBitrate =
+      std::max(encoder_start_bitrate_bps_ / 1000, video_codec.minBitrate);
+  video_codec.startBitrate =
+      std::min(video_codec.startBitrate, video_codec.maxBitrate);
 
   bool success = video_sender_.RegisterSendCodec(
-                     &codec, number_of_cores_,
-                     static_cast<uint32_t>(max_data_payload_length_)) == VCM_OK;
+                     &video_codec, number_of_cores_,
+                     static_cast<uint32_t>(max_data_payload_length)) == VCM_OK;
+
   if (!success) {
     LOG(LS_ERROR) << "Failed to configure encoder.";
     RTC_DCHECK(success);
   }
 
-  rate_allocator_.reset(new SimulcastRateAllocator(codec));
+  rate_allocator_.reset(new SimulcastRateAllocator(video_codec));
   if (stats_proxy_) {
     stats_proxy_->OnEncoderReconfigured(encoder_config_,
                                         rate_allocator_->GetPreferedBitrate());
   }
 
-  pending_encoder_reconfiguration_ = false;
-  if (stats_proxy_) {
-    stats_proxy_->OnEncoderReconfigured(encoder_config_,
-                                        rate_allocator_->GetPreferedBitrate());
-  }
   sink_->OnEncoderConfigurationChanged(
-      std::move(streams), encoder_config_.min_transmit_bitrate_bps);
+      encoder_config_.streams, encoder_config_.min_transmit_bitrate_bps);
 }
 
 void ViEEncoder::OnFrame(const VideoFrame& video_frame) {
@@ -541,24 +524,6 @@
   if (pre_encode_callback_)
     pre_encode_callback_->OnFrame(video_frame);
 
-  if (video_frame.width() != last_frame_info_->width ||
-      video_frame.height() != last_frame_info_->height ||
-      video_frame.rotation() != last_frame_info_->rotation ||
-      video_frame.is_texture() != last_frame_info_->is_texture) {
-    pending_encoder_reconfiguration_ = true;
-    last_frame_info_ = rtc::Optional<VideoFrameInfo>(
-        VideoFrameInfo(video_frame.width(), video_frame.height(),
-                       video_frame.rotation(), video_frame.is_texture()));
-    LOG(LS_INFO) << "Video frame parameters changed: dimensions="
-                 << last_frame_info_->width << "x" << last_frame_info_->height
-                 << ", rotation=" << last_frame_info_->rotation
-                 << ", texture=" << last_frame_info_->is_texture;
-  }
-
-  if (pending_encoder_reconfiguration_) {
-    ReconfigureEncoder();
-  }
-
   if (EncoderPaused()) {
     TraceFrameDropStart();
     return;
@@ -567,6 +532,16 @@
 
   TRACE_EVENT_ASYNC_STEP0("webrtc", "Video", video_frame.render_time_ms(),
                           "Encode");
+  const VideoFrame* frame_to_send = &video_frame;
+  // TODO(wuchengli): support texture frames.
+  if (!video_frame.video_frame_buffer()->native_handle()) {
+    // Pass frame via preprocessor.
+    frame_to_send = vp_->PreprocessFrame(video_frame);
+    if (!frame_to_send) {
+      // Drop this frame, or there was an error processing it.
+      return;
+    }
+  }
 
   overuse_detector_.FrameCaptured(video_frame, time_when_posted_in_ms);
 
@@ -585,10 +560,10 @@
       has_received_sli_ = false;
       has_received_rpsi_ = false;
 
-      video_sender_.AddVideoFrame(video_frame, &codec_specific_info);
-      return;
+    video_sender_.AddVideoFrame(*frame_to_send, &codec_specific_info);
+    return;
   }
-  video_sender_.AddVideoFrame(video_frame, nullptr);
+  video_sender_.AddVideoFrame(*frame_to_send, nullptr);
 }
 
 void ViEEncoder::SendKeyFrame() {
diff --git a/webrtc/video/vie_encoder.h b/webrtc/video/vie_encoder.h
index 68f043e..4196844 100644
--- a/webrtc/video/vie_encoder.h
+++ b/webrtc/video/vie_encoder.h
@@ -21,7 +21,6 @@
 #include "webrtc/base/task_queue.h"
 #include "webrtc/call.h"
 #include "webrtc/common_types.h"
-#include "webrtc/common_video/rotation.h"
 #include "webrtc/media/base/videosinkinterface.h"
 #include "webrtc/modules/video_coding/include/video_coding_defines.h"
 #include "webrtc/modules/video_coding/utility/simulcast_rate_allocator.h"
@@ -103,24 +102,8 @@
   class EncodeTask;
   class VideoSourceProxy;
 
-  struct VideoFrameInfo {
-    VideoFrameInfo(int width,
-                   int height,
-                   VideoRotation rotation,
-                   bool is_texture)
-        : width(width),
-          height(height),
-          rotation(rotation),
-          is_texture(is_texture) {}
-    int width;
-    int height;
-    webrtc::VideoRotation rotation;
-    bool is_texture;
-  };
-
   void ConfigureEncoderOnTaskQueue(VideoEncoderConfig config,
                                    size_t max_data_payload_length);
-  void ReconfigureEncoder();
 
   // Implements VideoSinkInterface.
   void OnFrame(const VideoFrame& video_frame) override;
@@ -155,6 +138,7 @@
   const VideoSendStream::Config::EncoderSettings settings_;
   const VideoCodecType codec_type_;
 
+  const std::unique_ptr<VideoProcessing> vp_;
   vcm::VideoSender video_sender_ ACCESS_ON(&encoder_queue_);
 
   OveruseFrameDetector overuse_detector_ ACCESS_ON(&encoder_queue_);
@@ -175,10 +159,6 @@
   std::unique_ptr<SimulcastRateAllocator> rate_allocator_
       ACCESS_ON(&encoder_queue_);
 
-  // Set when ConfigureEncoder has been called in order to lazy reconfigure the
-  // encoder on the next frame.
-  bool pending_encoder_reconfiguration_ ACCESS_ON(&encoder_queue_);
-  rtc::Optional<VideoFrameInfo> last_frame_info_ ACCESS_ON(&encoder_queue_);
   uint32_t encoder_start_bitrate_bps_ ACCESS_ON(&encoder_queue_);
   size_t max_data_payload_length_ ACCESS_ON(&encoder_queue_);
   uint32_t last_observed_bitrate_bps_ ACCESS_ON(&encoder_queue_);
diff --git a/webrtc/video/vie_encoder_unittest.cc b/webrtc/video/vie_encoder_unittest.cc
index 5d1544b..00e6cef 100644
--- a/webrtc/video/vie_encoder_unittest.cc
+++ b/webrtc/video/vie_encoder_unittest.cc
@@ -26,8 +26,6 @@
 
   ViEEncoderTest()
       : video_send_config_(VideoSendStream::Config(nullptr)),
-        codec_width_(320),
-        codec_height_(240),
         fake_encoder_(),
         stats_proxy_(Clock::GetRealTimeClock(),
                      video_send_config_,
@@ -41,7 +39,10 @@
     video_send_config_.encoder_settings.payload_type = 125;
 
     VideoEncoderConfig video_encoder_config;
-    test::FillEncoderConfiguration(1, &video_encoder_config);
+    video_encoder_config.streams = test::CreateVideoStreams(1);
+    codec_width_ = static_cast<int>(video_encoder_config.streams[0].width);
+    codec_height_ = static_cast<int>(video_encoder_config.streams[0].height);
+
     vie_encoder_.reset(new ViEEncoder(
         1 /* number_of_cores */, &stats_proxy_,
         video_send_config_.encoder_settings, nullptr /* pre_encode_callback */,
@@ -80,26 +81,6 @@
         : FakeEncoder(Clock::GetRealTimeClock()),
           continue_encode_event_(false, false) {}
 
-    VideoCodec codec_config() {
-      rtc::CritScope lock(&crit_);
-      return config_;
-    }
-
-    void BlockNextEncode() {
-      rtc::CritScope lock(&crit_);
-      block_next_encode_ = true;
-    }
-
-    void ContinueEncode() { continue_encode_event_.Set(); }
-
-    void CheckLastTimeStampsMatch(int64_t ntp_time_ms,
-                                  uint32_t timestamp) const {
-      rtc::CritScope lock(&crit_);
-      EXPECT_EQ(timestamp_, timestamp);
-      EXPECT_EQ(ntp_time_ms_, ntp_time_ms);
-    }
-
-   private:
     int32_t Encode(const VideoFrame& input_image,
                    const CodecSpecificInfo* codec_specific_info,
                    const std::vector<FrameType>* frame_types) override {
@@ -122,8 +103,21 @@
       return result;
     }
 
+    void BlockNextEncode() {
+      rtc::CritScope lock(&crit_);
+      block_next_encode_ = true;
+    }
 
+    void ContinueEncode() { continue_encode_event_.Set(); }
 
+    void CheckLastTimeStampsMatch(int64_t ntp_time_ms,
+                                  uint32_t timestamp) const {
+      rtc::CritScope lock(&crit_);
+      EXPECT_EQ(timestamp_, timestamp);
+      EXPECT_EQ(ntp_time_ms_, ntp_time_ms);
+    }
+
+   private:
     rtc::CriticalSection crit_;
     bool block_next_encode_ = false;
     rtc::Event continue_encode_event_;
@@ -290,46 +284,18 @@
   // Capture a frame and wait for it to synchronize with the encoder thread.
   video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
   sink_.WaitForEncodedFrame(1);
-  // The encoder will have been configured twice. First time before the first
-  // frame has been received. Then a second time when the resolution is known.
-  EXPECT_EQ(2, sink_.number_of_reconfigurations());
+  EXPECT_EQ(1, sink_.number_of_reconfigurations());
 
   VideoEncoderConfig video_encoder_config;
-  test::FillEncoderConfiguration(1, &video_encoder_config);
+  video_encoder_config.streams = test::CreateVideoStreams(1);
   video_encoder_config.min_transmit_bitrate_bps = 9999;
   vie_encoder_->ConfigureEncoder(std::move(video_encoder_config), 1440);
 
   // Capture a frame and wait for it to synchronize with the encoder thread.
   video_source_.IncomingCapturedFrame(CreateFrame(2, nullptr));
   sink_.WaitForEncodedFrame(2);
-  EXPECT_EQ(3, sink_.number_of_reconfigurations());
-  EXPECT_EQ(9999, sink_.last_min_transmit_bitrate());
-
-  vie_encoder_->Stop();
-}
-
-TEST_F(ViEEncoderTest, FrameResolutionChangeReconfigureEncoder) {
-  const int kTargetBitrateBps = 100000;
-  vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
-
-  // Capture a frame and wait for it to synchronize with the encoder thread.
-  video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
-  sink_.WaitForEncodedFrame(1);
-  // The encoder will have been configured twice. First time before the first
-  // frame has been received. Then a second time when the resolution is known.
   EXPECT_EQ(2, sink_.number_of_reconfigurations());
-  EXPECT_EQ(codec_width_, fake_encoder_.codec_config().width);
-  EXPECT_EQ(codec_height_, fake_encoder_.codec_config().height);
-
-  codec_width_ *= 2;
-  codec_height_ *= 2;
-  // Capture a frame with a higher resolution and wait for it to synchronize
-  // with the encoder thread.
-  video_source_.IncomingCapturedFrame(CreateFrame(2, nullptr));
-  sink_.WaitForEncodedFrame(2);
-  EXPECT_EQ(codec_width_, fake_encoder_.codec_config().width);
-  EXPECT_EQ(codec_height_, fake_encoder_.codec_config().height);
-  EXPECT_EQ(3, sink_.number_of_reconfigurations());
+  EXPECT_EQ(9999, sink_.last_min_transmit_bitrate());
 
   vie_encoder_->Stop();
 }
diff --git a/webrtc/video_frame.h b/webrtc/video_frame.h
index 8fbfb59..17dc496 100644
--- a/webrtc/video_frame.h
+++ b/webrtc/video_frame.h
@@ -172,7 +172,7 @@
       const;
 
   // Return true if the frame is stored in a texture.
-  bool is_texture() const {
+  bool is_texture() {
     return video_frame_buffer() &&
            video_frame_buffer()->native_handle() != nullptr;
   }