Reland "Inform VideoEncoder of negotiated capabilities"

This is a reland of 11dfff0878c949f2e19d95a0ddc209cdad94b3b4

Now that I am sure that WebRTC code is not calling the obsolete
versions, I will just remove the NOT_REACHED and call the
new version from the old ones, so as not to trip up downstream
projects.

Original change's description:
> Inform VideoEncoder of negotiated capabilities
>
> After this CL lands, an announcement will be made to
> discuss-webrtc about the deprecation of one version
> of InitEncode().
>
> Bug: webrtc:10720
> Change-Id: Ib992af0272bbb16ae16ef7e69491f365702d179e
> Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/140884
> Reviewed-by: Karl Wiberg <kwiberg@webrtc.org>
> Reviewed-by: Sami Kalliomäki <sakal@webrtc.org>
> Reviewed-by: Erik Språng <sprang@webrtc.org>
> Commit-Queue: Elad Alon <eladalon@webrtc.org>
> Cr-Commit-Position: refs/heads/master@{#28224}

TBR=sakal@webrtc.org,kwiberg@webrtc.org,sprang@webrtc.org

Bug: webrtc:10720
Change-Id: I46c69e45c190805c07f7e51acbe277d7eebd1600
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/141412
Commit-Queue: Elad Alon <eladalon@webrtc.org>
Reviewed-by: Elad Alon <eladalon@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#28236}
diff --git a/api/test/mock_video_encoder.h b/api/test/mock_video_encoder.h
index 9333b89..adc6859 100644
--- a/api/test/mock_video_encoder.h
+++ b/api/test/mock_video_encoder.h
@@ -37,6 +37,10 @@
                int32_t(const VideoCodec* codecSettings,
                        int32_t numberOfCores,
                        size_t maxPayloadSize));
+  MOCK_METHOD2(InitEncode,
+               int32_t(const VideoCodec* codecSettings,
+                       const VideoEncoder::Settings& settings));
+
   MOCK_METHOD2(Encode,
                int32_t(const VideoFrame& inputImage,
                        const std::vector<VideoFrameType>* frame_types));
diff --git a/api/video/video_stream_encoder_settings.h b/api/video/video_stream_encoder_settings.h
index 37c1de7..0183d4c 100644
--- a/api/video/video_stream_encoder_settings.h
+++ b/api/video/video_stream_encoder_settings.h
@@ -12,12 +12,15 @@
 #define API_VIDEO_VIDEO_STREAM_ENCODER_SETTINGS_H_
 
 #include "api/video/video_bitrate_allocator_factory.h"
+#include "api/video_codecs/video_encoder.h"
 #include "api/video_codecs/video_encoder_factory.h"
 
 namespace webrtc {
 
 struct VideoStreamEncoderSettings {
-  VideoStreamEncoderSettings() = default;
+  explicit VideoStreamEncoderSettings(
+      const VideoEncoder::Capabilities& capabilities)
+      : capabilities(capabilities) {}
 
   // Enables the new method to estimate the cpu load from encoding, used for
   // cpu adaptation.
@@ -28,6 +31,10 @@
 
   // Ownership stays with WebrtcVideoEngine (delegated from PeerConnection).
   VideoBitrateAllocatorFactory* bitrate_allocator_factory = nullptr;
+
+  // Negotiated capabilities which the VideoEncoder may expect the other
+  // side to use.
+  VideoEncoder::Capabilities capabilities;
 };
 
 }  // namespace webrtc
diff --git a/api/video_codecs/test/video_encoder_software_fallback_wrapper_unittest.cc b/api/video_codecs/test/video_encoder_software_fallback_wrapper_unittest.cc
index 201afc8..55afb68 100644
--- a/api/video_codecs/test/video_encoder_software_fallback_wrapper_unittest.cc
+++ b/api/video_codecs/test/video_encoder_software_fallback_wrapper_unittest.cc
@@ -50,6 +50,11 @@
 const int kLowThreshold = 10;
 const int kHighThreshold = 20;
 
+const VideoEncoder::Capabilities kCapabilities(false);
+const VideoEncoder::Settings kSettings(kCapabilities,
+                                       kNumCores,
+                                       kMaxPayloadSize);
+
 VideoEncoder::EncoderInfo GetEncoderInfoWithTrustedRateController(
     bool trusted_rate_controller) {
   VideoEncoder::EncoderInfo info;
@@ -87,11 +92,11 @@
   class CountingFakeEncoder : public VideoEncoder {
    public:
     int32_t InitEncode(const VideoCodec* codec_settings,
-                       int32_t number_of_cores,
-                       size_t max_payload_size) override {
+                       const VideoEncoder::Settings& settings) override {
       ++init_encode_count_;
       return init_encode_return_code_;
     }
+
     int32_t Encode(const VideoFrame& frame,
                    const std::vector<VideoFrameType>* frame_types) override {
       ++encode_count_;
@@ -202,7 +207,7 @@
 
   fake_encoder_->init_encode_return_code_ = WEBRTC_VIDEO_CODEC_ERROR;
   EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
-            fallback_wrapper_->InitEncode(&codec_, kNumCores, kMaxPayloadSize));
+            fallback_wrapper_->InitEncode(&codec_, kSettings));
   fallback_wrapper_->SetRates(VideoEncoder::RateControlParameters(
       rate_allocator_->GetAllocation(300000, kFramerate), kFramerate));
 
@@ -221,7 +226,7 @@
   codec_.height = kHeight;
   codec_.VP8()->numberOfTemporalLayers = 1;
   rate_allocator_.reset(new SimulcastRateAllocator(codec_));
-  fallback_wrapper_->InitEncode(&codec_, 2, kMaxPayloadSize);
+  fallback_wrapper_->InitEncode(&codec_, kSettings);
   fallback_wrapper_->SetRates(VideoEncoder::RateControlParameters(
       rate_allocator_->GetAllocation(300000, kFramerate), kFramerate));
   EXPECT_EQ(1, fake_encoder_->init_encode_count_);
@@ -238,7 +243,7 @@
 
 TEST_F(VideoEncoderSoftwareFallbackWrapperTest, InitializesEncoder) {
   VideoCodec codec = {};
-  fallback_wrapper_->InitEncode(&codec, 2, kMaxPayloadSize);
+  fallback_wrapper_->InitEncode(&codec, kSettings);
   EXPECT_EQ(1, fake_encoder_->init_encode_count_);
 }
 
@@ -324,7 +329,7 @@
   codec_.width = kWidth;
   codec_.height = kHeight;
   fallback_wrapper_->RegisterEncodeCompleteCallback(&callback_);
-  fallback_wrapper_->InitEncode(&codec_, kNumCores, kMaxPayloadSize);
+  fallback_wrapper_->InitEncode(&codec_, kSettings);
   EncodeFrame();
   CheckLastEncoderName("fake-encoder");
 }
@@ -375,8 +380,8 @@
   void InitEncode(int width, int height) {
     codec_.width = width;
     codec_.height = height;
-    EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_->InitEncode(
-                                         &codec_, kNumCores, kMaxPayloadSize));
+    EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
+              fallback_wrapper_->InitEncode(&codec_, kSettings));
     SetRateAllocation(kBitrateKbps);
   }
 
@@ -590,6 +595,9 @@
           std::unique_ptr<VideoEncoder>(hw_encoder));
   EXPECT_TRUE(wrapper->GetEncoderInfo().has_trusted_rate_controller);
 
+  VideoCodec codec_ = {};
+  wrapper->InitEncode(&codec_, kSettings);
+
   // Trigger fallback to software.
   EXPECT_CALL(*hw_encoder, Encode)
       .WillOnce(Return(WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE));
@@ -630,6 +638,9 @@
           std::unique_ptr<VideoEncoder>(hw_encoder));
   EXPECT_TRUE(wrapper->GetEncoderInfo().is_hardware_accelerated);
 
+  VideoCodec codec_ = {};
+  wrapper->InitEncode(&codec_, kSettings);
+
   // Trigger fallback to software.
   EXPECT_CALL(*hw_encoder, Encode)
       .WillOnce(Return(WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE));
@@ -654,6 +665,9 @@
           std::unique_ptr<VideoEncoder>(hw_encoder));
   EXPECT_TRUE(wrapper->GetEncoderInfo().has_internal_source);
 
+  VideoCodec codec_ = {};
+  wrapper->InitEncode(&codec_, kSettings);
+
   // Trigger fallback to software.
   EXPECT_CALL(*hw_encoder, Encode)
       .WillOnce(Return(WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE));
diff --git a/api/video_codecs/video_encoder.cc b/api/video_codecs/video_encoder.cc
index 710d90d..ffdcf8b 100644
--- a/api/video_codecs/video_encoder.cc
+++ b/api/video_codecs/video_encoder.cc
@@ -118,6 +118,29 @@
 
 VideoEncoder::RateControlParameters::~RateControlParameters() = default;
 
+int32_t VideoEncoder::InitEncode(const VideoCodec* codec_settings,
+                                 int32_t number_of_cores,
+                                 size_t max_payload_size) {
+  const VideoEncoder::Capabilities capabilities(/* loss_notification= */ false);
+  const VideoEncoder::Settings settings(capabilities, number_of_cores,
+                                        max_payload_size);
+  // In theory, this and the other version of InitEncode() could end up calling
+  // each other in a loop until we get a stack overflow.
+  // In practice, any subclass of VideoEncoder would overload at least one
+  // of these, and we have a TODO in the header file to make this pure virtual.
+  return InitEncode(codec_settings, settings);
+}
+
+int VideoEncoder::InitEncode(const VideoCodec* codec_settings,
+                             const VideoEncoder::Settings& settings) {
+  // In theory, this and the other version of InitEncode() could end up calling
+  // each other in a loop until we get a stack overflow.
+  // In practice, any subclass of VideoEncoder would overload at least one
+  // of these, and we have a TODO in the header file to make this pure virtual.
+  return InitEncode(codec_settings, settings.number_of_cores,
+                    settings.max_payload_size);
+}
+
 void VideoEncoder::OnPacketLossRateUpdate(float packet_loss_rate) {}
 
 void VideoEncoder::OnRttUpdate(int64_t rtt_ms) {}
diff --git a/api/video_codecs/video_encoder.h b/api/video_codecs/video_encoder.h
index c01309f..d2e4877 100644
--- a/api/video_codecs/video_encoder.h
+++ b/api/video_codecs/video_encoder.h
@@ -86,6 +86,7 @@
     int low;
     int high;
   };
+
   // Quality scaling is enabled if thresholds are provided.
   struct ScalingSettings {
    private:
@@ -237,6 +238,27 @@
     absl::optional<bool> last_received_decodable;
   };
 
+  // Negotiated capabilities which the VideoEncoder may expect the other
+  // side to use.
+  struct Capabilities {
+    explicit Capabilities(bool loss_notification)
+        : loss_notification(loss_notification) {}
+    bool loss_notification;
+  };
+
+  struct Settings {
+    Settings(const Capabilities& capabilities,
+             int number_of_cores,
+             size_t max_payload_size)
+        : capabilities(capabilities),
+          number_of_cores(number_of_cores),
+          max_payload_size(max_payload_size) {}
+
+    Capabilities capabilities;
+    int number_of_cores;
+    size_t max_payload_size;
+  };
+
   static VideoCodecVP8 GetDefaultVp8Settings();
   static VideoCodecVP9 GetDefaultVp9Settings();
   static VideoCodecH264 GetDefaultH264Settings();
@@ -247,6 +269,8 @@
   //
   // Input:
   //          - codec_settings    : Codec settings
+  //          - settings          : Settings affecting the encoding itself.
+  // Input for deprecated version:
   //          - number_of_cores   : Number of cores available for the encoder
   //          - max_payload_size  : The maximum size each payload is allowed
   //                                to have. Usually MTU - overhead.
@@ -257,9 +281,15 @@
   //                                  WEBRTC_VIDEO_CODEC_ERR_SIZE
   //                                  WEBRTC_VIDEO_CODEC_MEMORY
   //                                  WEBRTC_VIDEO_CODEC_ERROR
-  virtual int32_t InitEncode(const VideoCodec* codec_settings,
-                             int32_t number_of_cores,
-                             size_t max_payload_size) = 0;
+  // TODO(bugs.webrtc.org/10720): After updating downstream projects and posting
+  // an announcement to discuss-webrtc, remove the three-parameters variant
+  // and make the two-parameters variant pure-virtual.
+  /* RTC_DEPRECATED */ virtual int32_t InitEncode(
+      const VideoCodec* codec_settings,
+      int32_t number_of_cores,
+      size_t max_payload_size);
+  virtual int InitEncode(const VideoCodec* codec_settings,
+                         const VideoEncoder::Settings& settings);
 
   // Register an encode complete callback object.
   //
diff --git a/api/video_codecs/video_encoder_software_fallback_wrapper.cc b/api/video_codecs/video_encoder_software_fallback_wrapper.cc
index a687b84..1ccc5a2 100644
--- a/api/video_codecs/video_encoder_software_fallback_wrapper.cc
+++ b/api/video_codecs/video_encoder_software_fallback_wrapper.cc
@@ -21,6 +21,7 @@
 #include "api/video/video_bitrate_allocation.h"
 #include "api/video/video_frame.h"
 #include "api/video_codecs/video_codec.h"
+#include "api/video_codecs/video_encoder.h"
 #include "modules/video_coding/include/video_error_codes.h"
 #include "rtc_base/checks.h"
 #include "rtc_base/logging.h"
@@ -79,8 +80,7 @@
   ~VideoEncoderSoftwareFallbackWrapper() override;
 
   int32_t InitEncode(const VideoCodec* codec_settings,
-                     int32_t number_of_cores,
-                     size_t max_payload_size) override;
+                     const VideoEncoder::Settings& settings) override;
 
   int32_t RegisterEncodeCompleteCallback(
       EncodedImageCallback* callback) override;
@@ -118,8 +118,7 @@
   // Settings used in the last InitEncode call and used if a dynamic fallback to
   // software is required.
   VideoCodec codec_settings_;
-  int32_t number_of_cores_;
-  size_t max_payload_size_;
+  absl::optional<VideoEncoder::Settings> encoder_settings_;
 
   // The last rate control settings, if set.
   absl::optional<RateControlParameters> rate_control_parameters_;
@@ -142,9 +141,7 @@
 VideoEncoderSoftwareFallbackWrapper::VideoEncoderSoftwareFallbackWrapper(
     std::unique_ptr<webrtc::VideoEncoder> sw_encoder,
     std::unique_ptr<webrtc::VideoEncoder> hw_encoder)
-    : number_of_cores_(0),
-      max_payload_size_(0),
-      channel_parameters_set_(false),
+    : channel_parameters_set_(false),
       packet_loss_(0),
       rtt_(0),
       use_fallback_encoder_(false),
@@ -165,8 +162,9 @@
 bool VideoEncoderSoftwareFallbackWrapper::InitFallbackEncoder() {
   RTC_LOG(LS_WARNING) << "Encoder falling back to software encoding.";
 
-  const int ret = fallback_encoder_->InitEncode(
-      &codec_settings_, number_of_cores_, max_payload_size_);
+  RTC_DCHECK(encoder_settings_.has_value());
+  const int ret = fallback_encoder_->InitEncode(&codec_settings_,
+                                                encoder_settings_.value());
   use_fallback_encoder_ = (ret == WEBRTC_VIDEO_CODEC_OK);
   if (!use_fallback_encoder_) {
     RTC_LOG(LS_ERROR) << "Failed to initialize software-encoder fallback.";
@@ -188,13 +186,11 @@
 
 int32_t VideoEncoderSoftwareFallbackWrapper::InitEncode(
     const VideoCodec* codec_settings,
-    int32_t number_of_cores,
-    size_t max_payload_size) {
+    const VideoEncoder::Settings& settings) {
   // Store settings, in case we need to dynamically switch to the fallback
   // encoder after a failed Encode call.
   codec_settings_ = *codec_settings;
-  number_of_cores_ = number_of_cores;
-  max_payload_size_ = max_payload_size;
+  encoder_settings_ = settings;
   // Clear stored rate/channel parameters.
   rate_control_parameters_ = absl::nullopt;
   ValidateSettingsForForcedFallback();
@@ -209,8 +205,7 @@
   }
   forced_fallback_.active_ = false;
 
-  int32_t ret =
-      encoder_->InitEncode(codec_settings, number_of_cores, max_payload_size);
+  int32_t ret = encoder_->InitEncode(codec_settings, settings);
   if (ret == WEBRTC_VIDEO_CODEC_OK) {
     if (use_fallback_encoder_) {
       RTC_LOG(LS_WARNING)
@@ -319,14 +314,17 @@
   if (!IsForcedFallbackActive()) {
     return false;
   }
+
   // Forced fallback active.
   if (!forced_fallback_.IsValid(codec_settings_)) {
     RTC_LOG(LS_INFO) << "Stop forced SW encoder fallback, max pixels exceeded.";
     return false;
   }
+
   // Settings valid, reinitialize the forced fallback encoder.
-  if (fallback_encoder_->InitEncode(&codec_settings_, number_of_cores_,
-                                    max_payload_size_) !=
+  RTC_DCHECK(encoder_settings_.has_value());
+  if (fallback_encoder_->InitEncode(&codec_settings_,
+                                    encoder_settings_.value()) !=
       WEBRTC_VIDEO_CODEC_OK) {
     RTC_LOG(LS_ERROR) << "Failed to init forced SW encoder fallback.";
     return false;
diff --git a/call/call_perf_tests.cc b/call/call_perf_tests.cc
index 0bbf034..d869c87 100644
--- a/call/call_perf_tests.cc
+++ b/call/call_perf_tests.cc
@@ -18,6 +18,7 @@
 #include "api/test/simulated_network.h"
 #include "api/video/builtin_video_bitrate_allocator_factory.h"
 #include "api/video/video_bitrate_allocation.h"
+#include "api/video_codecs/video_encoder.h"
 #include "api/video_codecs/video_encoder_config.h"
 #include "call/call.h"
 #include "call/fake_network_pipe.h"
@@ -749,8 +750,7 @@
               CreateBuiltinVideoBitrateAllocatorFactory()) {}
 
     int32_t InitEncode(const VideoCodec* config,
-                       int32_t number_of_cores,
-                       size_t max_payload_size) override {
+                       const VideoEncoder::Settings& settings) override {
       ++encoder_inits_;
       if (encoder_inits_ == 1) {
         // First time initialization. Frame size is known.
@@ -771,7 +771,7 @@
             << "Encoder reconfigured with bitrate too far away from last set.";
         observation_complete_.Set();
       }
-      return FakeEncoder::InitEncode(config, number_of_cores, max_payload_size);
+      return FakeEncoder::InitEncode(config, settings);
     }
 
     void SetRates(const RateControlParameters& parameters) override {
diff --git a/call/video_send_stream.cc b/call/video_send_stream.cc
index fa2d4f2..dac4029 100644
--- a/call/video_send_stream.cc
+++ b/call/video_send_stream.cc
@@ -77,7 +77,10 @@
 VideoSendStream::Config::Config(Config&&) = default;
 VideoSendStream::Config::Config(Transport* send_transport,
                                 MediaTransportInterface* media_transport)
-    : send_transport(send_transport), media_transport(media_transport) {}
+    : rtp(),
+      encoder_settings(VideoEncoder::Capabilities(rtp.lntf.enabled)),
+      send_transport(send_transport),
+      media_transport(media_transport) {}
 VideoSendStream::Config::Config(Transport* send_transport)
     : Config(send_transport, nullptr) {}
 
diff --git a/call/video_send_stream.h b/call/video_send_stream.h
index 850996e..f38f7bc 100644
--- a/call/video_send_stream.h
+++ b/call/video_send_stream.h
@@ -126,10 +126,10 @@
 
     std::string ToString() const;
 
-    VideoStreamEncoderSettings encoder_settings;
-
     RtpConfig rtp;
 
+    VideoStreamEncoderSettings encoder_settings;
+
     // Time interval between RTCP report for video
     int rtcp_report_interval_ms = 1000;
 
diff --git a/media/engine/encoder_simulcast_proxy.cc b/media/engine/encoder_simulcast_proxy.cc
index 88cff1b..da769a9 100644
--- a/media/engine/encoder_simulcast_proxy.cc
+++ b/media/engine/encoder_simulcast_proxy.cc
@@ -10,10 +10,12 @@
 
 #include "media/engine/encoder_simulcast_proxy.h"
 
+#include "api/video_codecs/video_encoder.h"
 #include "media/engine/simulcast_encoder_adapter.h"
 #include "modules/video_coding/include/video_error_codes.h"
 
 namespace webrtc {
+
 EncoderSimulcastProxy::EncoderSimulcastProxy(VideoEncoderFactory* factory,
                                              const SdpVideoFormat& format)
     : factory_(factory), video_format_(format), callback_(nullptr) {
@@ -29,16 +31,16 @@
   return encoder_->Release();
 }
 
+// TODO(eladalon): s/inst/codec_settings/g.
 int EncoderSimulcastProxy::InitEncode(const VideoCodec* inst,
-                                      int number_of_cores,
-                                      size_t max_payload_size) {
-  int ret = encoder_->InitEncode(inst, number_of_cores, max_payload_size);
+                                      const VideoEncoder::Settings& settings) {
+  int ret = encoder_->InitEncode(inst, settings);
   if (ret == WEBRTC_VIDEO_CODEC_ERR_SIMULCAST_PARAMETERS_NOT_SUPPORTED) {
     encoder_.reset(new SimulcastEncoderAdapter(factory_, video_format_));
     if (callback_) {
       encoder_->RegisterEncodeCompleteCallback(callback_);
     }
-    ret = encoder_->InitEncode(inst, number_of_cores, max_payload_size);
+    ret = encoder_->InitEncode(inst, settings);
   }
   return ret;
 }
diff --git a/media/engine/encoder_simulcast_proxy.h b/media/engine/encoder_simulcast_proxy.h
index 41ffcba..7709aa2 100644
--- a/media/engine/encoder_simulcast_proxy.h
+++ b/media/engine/encoder_simulcast_proxy.h
@@ -42,9 +42,8 @@
 
   // Implements VideoEncoder.
   int Release() override;
-  int InitEncode(const VideoCodec* inst,
-                 int number_of_cores,
-                 size_t max_payload_size) override;
+  int InitEncode(const VideoCodec* codec_settings,
+                 const VideoEncoder::Settings& settings) override;
   int Encode(const VideoFrame& input_image,
              const std::vector<VideoFrameType>* frame_types) override;
   int RegisterEncodeCompleteCallback(EncodedImageCallback* callback) override;
diff --git a/media/engine/encoder_simulcast_proxy_unittest.cc b/media/engine/encoder_simulcast_proxy_unittest.cc
index daa4d3e..f52575a7 100644
--- a/media/engine/encoder_simulcast_proxy_unittest.cc
+++ b/media/engine/encoder_simulcast_proxy_unittest.cc
@@ -14,6 +14,7 @@
 
 #include "api/test/mock_video_encoder.h"
 #include "api/test/mock_video_encoder_factory.h"
+#include "api/video_codecs/video_encoder.h"
 #include "api/video_codecs/vp8_temporal_layers.h"
 #include "modules/video_coding/include/video_codec_interface.h"
 #include "test/gmock.h"
@@ -22,6 +23,10 @@
 
 namespace webrtc {
 namespace testing {
+namespace {
+const VideoEncoder::Capabilities kCapabilities(false);
+const VideoEncoder::Settings kSettings(kCapabilities, 4, 1200);
+}  // namespace
 
 using ::testing::_;
 using ::testing::NiceMock;
@@ -62,7 +67,7 @@
   NiceMock<MockVideoEncoder>* mock_encoder = new NiceMock<MockVideoEncoder>();
   NiceMock<MockVideoEncoderFactory> simulcast_factory;
 
-  EXPECT_CALL(*mock_encoder, InitEncode(_, _, _))
+  EXPECT_CALL(*mock_encoder, InitEncode(_, _))
       .WillOnce(Return(WEBRTC_VIDEO_CODEC_OK));
   VideoEncoder::EncoderInfo encoder_info;
   encoder_info.implementation_name = kImplementationName;
@@ -76,7 +81,7 @@
   EncoderSimulcastProxy simulcast_enabled_proxy(&simulcast_factory,
                                                 SdpVideoFormat("VP8"));
   EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
-            simulcast_enabled_proxy.InitEncode(&codec_settings, 4, 1200));
+            simulcast_enabled_proxy.InitEncode(&codec_settings, kSettings));
   EXPECT_EQ(kImplementationName,
             simulcast_enabled_proxy.GetEncoderInfo().implementation_name);
 
@@ -86,23 +91,23 @@
   NiceMock<MockVideoEncoder>* mock_encoder4 = new NiceMock<MockVideoEncoder>();
   NiceMock<MockVideoEncoderFactory> nonsimulcast_factory;
 
-  EXPECT_CALL(*mock_encoder1, InitEncode(_, _, _))
+  EXPECT_CALL(*mock_encoder1, InitEncode(_, _))
       .WillOnce(
           Return(WEBRTC_VIDEO_CODEC_ERR_SIMULCAST_PARAMETERS_NOT_SUPPORTED));
   EXPECT_CALL(*mock_encoder1, GetEncoderInfo())
       .WillRepeatedly(Return(encoder_info));
 
-  EXPECT_CALL(*mock_encoder2, InitEncode(_, _, _))
+  EXPECT_CALL(*mock_encoder2, InitEncode(_, _))
       .WillOnce(Return(WEBRTC_VIDEO_CODEC_OK));
   EXPECT_CALL(*mock_encoder2, GetEncoderInfo())
       .WillRepeatedly(Return(encoder_info));
 
-  EXPECT_CALL(*mock_encoder3, InitEncode(_, _, _))
+  EXPECT_CALL(*mock_encoder3, InitEncode(_, _))
       .WillOnce(Return(WEBRTC_VIDEO_CODEC_OK));
   EXPECT_CALL(*mock_encoder3, GetEncoderInfo())
       .WillRepeatedly(Return(encoder_info));
 
-  EXPECT_CALL(*mock_encoder4, InitEncode(_, _, _))
+  EXPECT_CALL(*mock_encoder4, InitEncode(_, _))
       .WillOnce(Return(WEBRTC_VIDEO_CODEC_OK));
   EXPECT_CALL(*mock_encoder4, GetEncoderInfo())
       .WillRepeatedly(Return(encoder_info));
@@ -117,7 +122,7 @@
   EncoderSimulcastProxy simulcast_disabled_proxy(&nonsimulcast_factory,
                                                  SdpVideoFormat("VP8"));
   EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
-            simulcast_disabled_proxy.InitEncode(&codec_settings, 4, 1200));
+            simulcast_disabled_proxy.InitEncode(&codec_settings, kSettings));
   EXPECT_EQ(kSimulcastAdaptedImplementationName,
             simulcast_disabled_proxy.GetEncoderInfo().implementation_name);
 
@@ -130,7 +135,7 @@
   NiceMock<MockVideoEncoder>* mock_encoder = new NiceMock<MockVideoEncoder>();
   NiceMock<MockVideoEncoderFactory> simulcast_factory;
 
-  EXPECT_CALL(*mock_encoder, InitEncode(_, _, _))
+  EXPECT_CALL(*mock_encoder, InitEncode(_, _))
       .WillOnce(Return(WEBRTC_VIDEO_CODEC_OK));
 
   EXPECT_CALL(simulcast_factory, CreateVideoEncoderProxy(_))
@@ -142,7 +147,7 @@
   VideoCodec codec_settings;
   webrtc::test::CodecSettings(kVideoCodecVP8, &codec_settings);
   EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
-            simulcast_enabled_proxy.InitEncode(&codec_settings, 4, 1200));
+            simulcast_enabled_proxy.InitEncode(&codec_settings, kSettings));
 
   VideoEncoder::EncoderInfo info;
   info.has_trusted_rate_controller = true;
@@ -156,7 +161,7 @@
   NiceMock<MockVideoEncoder>* mock_encoder = new NiceMock<MockVideoEncoder>();
   NiceMock<MockVideoEncoderFactory> simulcast_factory;
 
-  EXPECT_CALL(*mock_encoder, InitEncode(_, _, _))
+  EXPECT_CALL(*mock_encoder, InitEncode(_, _))
       .WillOnce(Return(WEBRTC_VIDEO_CODEC_OK));
 
   EXPECT_CALL(simulcast_factory, CreateVideoEncoderProxy(_))
@@ -168,7 +173,7 @@
   VideoCodec codec_settings;
   webrtc::test::CodecSettings(kVideoCodecVP8, &codec_settings);
   EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
-            simulcast_enabled_proxy.InitEncode(&codec_settings, 4, 1200));
+            simulcast_enabled_proxy.InitEncode(&codec_settings, kSettings));
 
   VideoEncoder::EncoderInfo info;
 
@@ -186,7 +191,7 @@
   NiceMock<MockVideoEncoder>* mock_encoder = new NiceMock<MockVideoEncoder>();
   NiceMock<MockVideoEncoderFactory> simulcast_factory;
 
-  EXPECT_CALL(*mock_encoder, InitEncode(_, _, _))
+  EXPECT_CALL(*mock_encoder, InitEncode(_, _))
       .WillOnce(Return(WEBRTC_VIDEO_CODEC_OK));
 
   EXPECT_CALL(simulcast_factory, CreateVideoEncoderProxy(_))
@@ -198,7 +203,7 @@
   VideoCodec codec_settings;
   webrtc::test::CodecSettings(kVideoCodecVP8, &codec_settings);
   EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
-            simulcast_enabled_proxy.InitEncode(&codec_settings, 4, 1200));
+            simulcast_enabled_proxy.InitEncode(&codec_settings, kSettings));
 
   VideoEncoder::EncoderInfo info;
 
diff --git a/media/engine/fake_webrtc_video_engine.cc b/media/engine/fake_webrtc_video_engine.cc
index 7e7e3ce..bdc9178 100644
--- a/media/engine/fake_webrtc_video_engine.cc
+++ b/media/engine/fake_webrtc_video_engine.cc
@@ -139,8 +139,7 @@
 
 int32_t FakeWebRtcVideoEncoder::InitEncode(
     const webrtc::VideoCodec* codecSettings,
-    int32_t numberOfCores,
-    size_t maxPayloadSize) {
+    const VideoEncoder::Settings& settings) {
   rtc::CritScope lock(&crit_);
   codec_settings_ = *codecSettings;
   init_encode_event_.Set();
diff --git a/media/engine/fake_webrtc_video_engine.h b/media/engine/fake_webrtc_video_engine.h
index 3fea175..364ec9e 100644
--- a/media/engine/fake_webrtc_video_engine.h
+++ b/media/engine/fake_webrtc_video_engine.h
@@ -84,8 +84,7 @@
   ~FakeWebRtcVideoEncoder();
 
   int32_t InitEncode(const webrtc::VideoCodec* codecSettings,
-                     int32_t numberOfCores,
-                     size_t maxPayloadSize) override;
+                     const VideoEncoder::Settings& settings) override;
   int32_t Encode(
       const webrtc::VideoFrame& inputImage,
       const std::vector<webrtc::VideoFrameType>* frame_types) override;
diff --git a/media/engine/simulcast_encoder_adapter.cc b/media/engine/simulcast_encoder_adapter.cc
index b7b2d76..6d8bedb 100644
--- a/media/engine/simulcast_encoder_adapter.cc
+++ b/media/engine/simulcast_encoder_adapter.cc
@@ -22,6 +22,7 @@
 #include "api/video/video_codec_constants.h"
 #include "api/video/video_frame_buffer.h"
 #include "api/video/video_rotation.h"
+#include "api/video_codecs/video_encoder.h"
 #include "api/video_codecs/video_encoder_factory.h"
 #include "modules/video_coding/include/video_error_codes.h"
 #include "modules/video_coding/utility/simulcast_rate_allocator.h"
@@ -167,12 +168,13 @@
   return WEBRTC_VIDEO_CODEC_OK;
 }
 
-int SimulcastEncoderAdapter::InitEncode(const VideoCodec* inst,
-                                        int number_of_cores,
-                                        size_t max_payload_size) {
+// TODO(eladalon): s/inst/codec_settings/g.
+int SimulcastEncoderAdapter::InitEncode(
+    const VideoCodec* inst,
+    const VideoEncoder::Settings& settings) {
   RTC_DCHECK_RUN_ON(&encoder_queue_);
 
-  if (number_of_cores < 1) {
+  if (settings.number_of_cores < 1) {
     return WEBRTC_VIDEO_CODEC_ERR_PARAMETER;
   }
 
@@ -256,7 +258,7 @@
           codec_.codecType == webrtc::kVideoCodecVP8 ? "VP8" : "H264"));
     }
 
-    ret = encoder->InitEncode(&stream_codec, number_of_cores, max_payload_size);
+    ret = encoder->InitEncode(&stream_codec, settings);
     if (ret < 0) {
       // Explicitly destroy the current encoder; because we haven't registered a
       // StreamInfo for it yet, Release won't do anything about it.
diff --git a/media/engine/simulcast_encoder_adapter.h b/media/engine/simulcast_encoder_adapter.h
index 5bc0bec..9476256 100644
--- a/media/engine/simulcast_encoder_adapter.h
+++ b/media/engine/simulcast_encoder_adapter.h
@@ -20,6 +20,7 @@
 
 #include "absl/types/optional.h"
 #include "api/video_codecs/sdp_video_format.h"
+#include "api/video_codecs/video_encoder.h"
 #include "modules/video_coding/include/video_codec_interface.h"
 #include "rtc_base/atomic_ops.h"
 #include "rtc_base/synchronization/sequence_checker.h"
@@ -42,9 +43,8 @@
 
   // Implements VideoEncoder.
   int Release() override;
-  int InitEncode(const VideoCodec* inst,
-                 int number_of_cores,
-                 size_t max_payload_size) override;
+  int InitEncode(const VideoCodec* codec_settings,
+                 const VideoEncoder::Settings& settings) override;
   int Encode(const VideoFrame& input_image,
              const std::vector<VideoFrameType>* frame_types) override;
   int RegisterEncodeCompleteCallback(EncodedImageCallback* callback) override;
diff --git a/media/engine/simulcast_encoder_adapter_unittest.cc b/media/engine/simulcast_encoder_adapter_unittest.cc
index 1bab49a..6bf99a5 100644
--- a/media/engine/simulcast_encoder_adapter_unittest.cc
+++ b/media/engine/simulcast_encoder_adapter_unittest.cc
@@ -18,6 +18,7 @@
 #include "api/test/video/function_video_decoder_factory.h"
 #include "api/test/video/function_video_encoder_factory.h"
 #include "api/video_codecs/sdp_video_format.h"
+#include "api/video_codecs/video_encoder.h"
 #include "api/video_codecs/video_encoder_factory.h"
 #include "common_video/include/video_frame_buffer.h"
 #include "media/base/media_constants.h"
@@ -43,6 +44,9 @@
 constexpr int kDefaultWidth = 1280;
 constexpr int kDefaultHeight = 720;
 
+const VideoEncoder::Capabilities kCapabilities(false);
+const VideoEncoder::Settings kSettings(kCapabilities, 1, 1200);
+
 std::unique_ptr<SimulcastTestFixture> CreateSpecificSimulcastTestFixture(
     VideoEncoderFactory* internal_encoder_factory) {
   std::unique_ptr<VideoEncoderFactory> encoder_factory =
@@ -188,8 +192,7 @@
   // warnings from -Winconsistent-missing-override. See
   // http://crbug.com/428099.
   int32_t InitEncode(const VideoCodec* codecSettings,
-                     int32_t numberOfCores,
-                     size_t maxPayloadSize) /* override */ {
+                     const VideoEncoder::Settings& settings) /* override */ {
     codec_ = *codecSettings;
     return init_encode_return_value_;
   }
@@ -394,7 +397,7 @@
         &codec_, static_cast<const int*>(kTestTemporalLayerProfile),
         kVideoCodecVP8);
     rate_allocator_.reset(new SimulcastRateAllocator(codec_));
-    EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
+    EXPECT_EQ(0, adapter_->InitEncode(&codec_, kSettings));
     adapter_->RegisterEncodeCompleteCallback(this);
   }
 
@@ -491,7 +494,7 @@
   SetupCodec();
   EXPECT_EQ(0, adapter_->Release());
 
-  EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
+  EXPECT_EQ(0, adapter_->InitEncode(&codec_, kSettings));
 }
 
 TEST_F(TestSimulcastEncoderAdapterFake, EncodedCallbackForDifferentEncoders) {
@@ -557,7 +560,7 @@
   std::vector<VideoFrameType> frame_types;
 
   // Encode with three streams.
-  EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
+  EXPECT_EQ(0, adapter_->InitEncode(&codec_, kSettings));
   VerifyCodecSettings();
   adapter_->SetRates(VideoEncoder::RateControlParameters(
       rate_allocator_->GetAllocation(target_bitrate, 30), 30.0));
@@ -585,7 +588,7 @@
   codec_.width /= 2;
   codec_.height /= 2;
   codec_.numberOfSimulcastStreams = 2;
-  EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
+  EXPECT_EQ(0, adapter_->InitEncode(&codec_, kSettings));
   adapter_->SetRates(VideoEncoder::RateControlParameters(
       rate_allocator_->GetAllocation(target_bitrate, 30), 30.0));
   std::vector<MockVideoEncoder*> new_encoders = helper_->factory()->encoders();
@@ -608,7 +611,7 @@
   codec_.width /= 2;
   codec_.height /= 2;
   codec_.numberOfSimulcastStreams = 1;
-  EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
+  EXPECT_EQ(0, adapter_->InitEncode(&codec_, kSettings));
   adapter_->SetRates(VideoEncoder::RateControlParameters(
       rate_allocator_->GetAllocation(target_bitrate, 30), 30.0));
   new_encoders = helper_->factory()->encoders();
@@ -626,7 +629,7 @@
   codec_.width *= 4;
   codec_.height *= 4;
   codec_.numberOfSimulcastStreams = 3;
-  EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
+  EXPECT_EQ(0, adapter_->InitEncode(&codec_, kSettings));
   adapter_->SetRates(VideoEncoder::RateControlParameters(
       rate_allocator_->GetAllocation(target_bitrate, 30), 30.0));
   new_encoders = helper_->factory()->encoders();
@@ -680,7 +683,7 @@
 
   // Reinitialize and verify that the new codec settings are the same.
   EXPECT_EQ(0, adapter_->Release());
-  EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
+  EXPECT_EQ(0, adapter_->InitEncode(&codec_, kSettings));
   for (int i = 0; i < 3; ++i) {
     const VideoCodec& codec_before = codecs_before[i];
     const VideoCodec& codec_after = encoders[i]->codec();
@@ -735,7 +738,7 @@
 
   // Reinitialize.
   EXPECT_EQ(0, adapter_->Release());
-  EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
+  EXPECT_EQ(0, adapter_->InitEncode(&codec_, kSettings));
   adapter_->SetRates(VideoEncoder::RateControlParameters(
       rate_allocator_->GetAllocation(1200, 30), 30.0));
 
@@ -758,14 +761,14 @@
       &codec_, static_cast<const int*>(kTestTemporalLayerProfile),
       kVideoCodecVP8);
   codec_.numberOfSimulcastStreams = 1;
-  EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
+  EXPECT_EQ(0, adapter_->InitEncode(&codec_, kSettings));
   adapter_->RegisterEncodeCompleteCallback(this);
   ASSERT_EQ(1u, helper_->factory()->encoders().size());
   helper_->factory()->encoders()[0]->set_supports_native_handle(true);
-  EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
+  EXPECT_EQ(0, adapter_->InitEncode(&codec_, kSettings));
   EXPECT_TRUE(adapter_->GetEncoderInfo().supports_native_handle);
   helper_->factory()->encoders()[0]->set_supports_native_handle(false);
-  EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
+  EXPECT_EQ(0, adapter_->InitEncode(&codec_, kSettings));
   EXPECT_FALSE(adapter_->GetEncoderInfo().supports_native_handle);
 }
 
@@ -775,7 +778,7 @@
       kVideoCodecVP8);
   codec_.minBitrate = 50;
   codec_.numberOfSimulcastStreams = 1;
-  EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
+  EXPECT_EQ(0, adapter_->InitEncode(&codec_, kSettings));
   rate_allocator_.reset(new SimulcastRateAllocator(codec_));
 
   // Above min should be respected.
@@ -811,14 +814,14 @@
   encoder_names.push_back("codec2");
   encoder_names.push_back("codec3");
   helper_->factory()->SetEncoderNames(encoder_names);
-  EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
+  EXPECT_EQ(0, adapter_->InitEncode(&codec_, kSettings));
   EXPECT_EQ("SimulcastEncoderAdapter (codec1, codec2, codec3)",
             adapter_->GetEncoderInfo().implementation_name);
 
   // Single streams should not expose "SimulcastEncoderAdapter" in name.
   EXPECT_EQ(0, adapter_->Release());
   codec_.numberOfSimulcastStreams = 1;
-  EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
+  EXPECT_EQ(0, adapter_->InitEncode(&codec_, kSettings));
   adapter_->RegisterEncodeCompleteCallback(this);
   ASSERT_EQ(1u, helper_->factory()->encoders().size());
   EXPECT_EQ("codec1", adapter_->GetEncoderInfo().implementation_name);
@@ -830,7 +833,7 @@
       &codec_, static_cast<const int*>(kTestTemporalLayerProfile),
       kVideoCodecVP8);
   codec_.numberOfSimulcastStreams = 3;
-  EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
+  EXPECT_EQ(0, adapter_->InitEncode(&codec_, kSettings));
   adapter_->RegisterEncodeCompleteCallback(this);
   ASSERT_EQ(3u, helper_->factory()->encoders().size());
   for (MockVideoEncoder* encoder : helper_->factory()->encoders())
@@ -840,7 +843,7 @@
   EXPECT_FALSE(adapter_->GetEncoderInfo().supports_native_handle);
   // Once all do, then the adapter claims support.
   helper_->factory()->encoders()[0]->set_supports_native_handle(true);
-  EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
+  EXPECT_EQ(0, adapter_->InitEncode(&codec_, kSettings));
   EXPECT_TRUE(adapter_->GetEncoderInfo().supports_native_handle);
 }
 
@@ -872,12 +875,12 @@
   codec_.numberOfSimulcastStreams = 3;
   // High start bitrate, so all streams are enabled.
   codec_.startBitrate = 3000;
-  EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
+  EXPECT_EQ(0, adapter_->InitEncode(&codec_, kSettings));
   adapter_->RegisterEncodeCompleteCallback(this);
   ASSERT_EQ(3u, helper_->factory()->encoders().size());
   for (MockVideoEncoder* encoder : helper_->factory()->encoders())
     encoder->set_supports_native_handle(true);
-  EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
+  EXPECT_EQ(0, adapter_->InitEncode(&codec_, kSettings));
   EXPECT_TRUE(adapter_->GetEncoderInfo().supports_native_handle);
 
   rtc::scoped_refptr<VideoFrameBuffer> buffer(
@@ -901,7 +904,7 @@
       &codec_, static_cast<const int*>(kTestTemporalLayerProfile),
       kVideoCodecVP8);
   codec_.numberOfSimulcastStreams = 3;
-  EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
+  EXPECT_EQ(0, adapter_->InitEncode(&codec_, kSettings));
   adapter_->RegisterEncodeCompleteCallback(this);
   ASSERT_EQ(3u, helper_->factory()->encoders().size());
   // Tell the 2nd encoder to request software fallback.
@@ -931,7 +934,7 @@
   helper_->factory()->set_init_encode_return_value(
       WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE);
   EXPECT_EQ(WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE,
-            adapter_->InitEncode(&codec_, 1, 1200));
+            adapter_->InitEncode(&codec_, kSettings));
   EXPECT_TRUE(helper_->factory()->encoders().empty());
 }
 
@@ -946,7 +949,7 @@
   codec_.simulcastStream[0].qpMax = kHighMaxQp;
   codec_.mode = VideoCodecMode::kScreensharing;
 
-  EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
+  EXPECT_EQ(0, adapter_->InitEncode(&codec_, kSettings));
   EXPECT_EQ(3u, helper_->factory()->encoders().size());
 
   // Just check the lowest stream, which is the one that where the adapter
@@ -961,7 +964,7 @@
 
   // Change the max qp and try again.
   codec_.simulcastStream[0].qpMax = kLowMaxQp;
-  EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
+  EXPECT_EQ(0, adapter_->InitEncode(&codec_, kSettings));
   EXPECT_EQ(3u, helper_->factory()->encoders().size());
   ref_codec.qpMax = kLowMaxQp;
   VerifyCodec(ref_codec, 0);
@@ -979,7 +982,7 @@
   codec_.simulcastStream[2].qpMax = kHighMaxQp;
   codec_.mode = VideoCodecMode::kScreensharing;
 
-  EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
+  EXPECT_EQ(0, adapter_->InitEncode(&codec_, kSettings));
   EXPECT_EQ(3u, helper_->factory()->encoders().size());
 
   // Just check the lowest stream, which is the one that where the adapter
@@ -994,7 +997,7 @@
 
   // Change the max qp and try again.
   codec_.simulcastStream[2].qpMax = kLowMaxQp;
-  EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
+  EXPECT_EQ(0, adapter_->InitEncode(&codec_, kSettings));
   EXPECT_EQ(3u, helper_->factory()->encoders().size());
   ref_codec.qpMax = kLowMaxQp;
   VerifyCodec(ref_codec, 2);
@@ -1023,7 +1026,7 @@
                                .build();
 
   // Encode with three streams.
-  EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
+  EXPECT_EQ(0, adapter_->InitEncode(&codec_, kSettings));
   std::vector<MockVideoEncoder*> original_encoders =
       helper_->factory()->encoders();
   ASSERT_EQ(3u, original_encoders.size());
@@ -1061,7 +1064,7 @@
                                .build();
 
   // No encoder trusted, so simulcast adapter should not be either.
-  EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
+  EXPECT_EQ(0, adapter_->InitEncode(&codec_, kSettings));
   EXPECT_FALSE(adapter_->GetEncoderInfo().has_trusted_rate_controller);
 
   // Encode with three streams.
@@ -1072,18 +1075,18 @@
   original_encoders[0]->set_has_trusted_rate_controller(true);
   original_encoders[1]->set_has_trusted_rate_controller(true);
   original_encoders[2]->set_has_trusted_rate_controller(true);
-  EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
+  EXPECT_EQ(0, adapter_->InitEncode(&codec_, kSettings));
   EXPECT_TRUE(adapter_->GetEncoderInfo().has_trusted_rate_controller);
 
   // One encoder not trusted, so simulcast adapter should not be either.
   original_encoders[2]->set_has_trusted_rate_controller(false);
-  EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
+  EXPECT_EQ(0, adapter_->InitEncode(&codec_, kSettings));
   EXPECT_FALSE(adapter_->GetEncoderInfo().has_trusted_rate_controller);
 
   // No encoder trusted, so simulcast adapter should not be either.
   original_encoders[0]->set_has_trusted_rate_controller(false);
   original_encoders[1]->set_has_trusted_rate_controller(false);
-  EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
+  EXPECT_EQ(0, adapter_->InitEncode(&codec_, kSettings));
   EXPECT_FALSE(adapter_->GetEncoderInfo().has_trusted_rate_controller);
 }
 
@@ -1093,19 +1096,19 @@
       kVideoCodecVP8);
   codec_.numberOfSimulcastStreams = 3;
   adapter_->RegisterEncodeCompleteCallback(this);
-  EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
+  EXPECT_EQ(0, adapter_->InitEncode(&codec_, kSettings));
   ASSERT_EQ(3u, helper_->factory()->encoders().size());
 
   // None of the encoders uses HW support, so simulcast adapter reports false.
   for (MockVideoEncoder* encoder : helper_->factory()->encoders()) {
     encoder->set_is_hardware_accelerated(false);
   }
-  EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
+  EXPECT_EQ(0, adapter_->InitEncode(&codec_, kSettings));
   EXPECT_FALSE(adapter_->GetEncoderInfo().is_hardware_accelerated);
 
   // One encoder uses HW support, so simulcast adapter reports true.
   helper_->factory()->encoders()[2]->set_is_hardware_accelerated(true);
-  EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
+  EXPECT_EQ(0, adapter_->InitEncode(&codec_, kSettings));
   EXPECT_TRUE(adapter_->GetEncoderInfo().is_hardware_accelerated);
 }
 
@@ -1115,19 +1118,19 @@
       kVideoCodecVP8);
   codec_.numberOfSimulcastStreams = 3;
   adapter_->RegisterEncodeCompleteCallback(this);
-  EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
+  EXPECT_EQ(0, adapter_->InitEncode(&codec_, kSettings));
   ASSERT_EQ(3u, helper_->factory()->encoders().size());
 
   // All encoders have internal source, simulcast adapter reports true.
   for (MockVideoEncoder* encoder : helper_->factory()->encoders()) {
     encoder->set_has_internal_source(true);
   }
-  EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
+  EXPECT_EQ(0, adapter_->InitEncode(&codec_, kSettings));
   EXPECT_TRUE(adapter_->GetEncoderInfo().has_internal_source);
 
   // One encoder does not have internal source, simulcast adapter reports false.
   helper_->factory()->encoders()[2]->set_has_internal_source(false);
-  EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
+  EXPECT_EQ(0, adapter_->InitEncode(&codec_, kSettings));
   EXPECT_FALSE(adapter_->GetEncoderInfo().has_internal_source);
 }
 
@@ -1137,7 +1140,7 @@
       kVideoCodecVP8);
   codec_.numberOfSimulcastStreams = 3;
   adapter_->RegisterEncodeCompleteCallback(this);
-  EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
+  EXPECT_EQ(0, adapter_->InitEncode(&codec_, kSettings));
   ASSERT_EQ(3u, helper_->factory()->encoders().size());
 
   // Combination of three different supported mode:
@@ -1155,7 +1158,7 @@
     MockVideoEncoder* encoder = helper_->factory()->encoders()[i];
     encoder->set_fps_allocation(expected_fps_allocation[i]);
   }
-  EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
+  EXPECT_EQ(0, adapter_->InitEncode(&codec_, kSettings));
   EXPECT_THAT(adapter_->GetEncoderInfo().fps_allocation,
               ::testing::ElementsAreArray(expected_fps_allocation));
 }
@@ -1172,7 +1175,7 @@
   const DataRate bandwidth_allocation = target_bitrate + DataRate::kbps(600);
 
   rate_allocator_.reset(new SimulcastRateAllocator(codec_));
-  EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
+  EXPECT_EQ(0, adapter_->InitEncode(&codec_, kSettings));
   adapter_->RegisterEncodeCompleteCallback(this);
 
   // Set bitrates so that we send all layers.
diff --git a/media/engine/webrtc_video_engine.cc b/media/engine/webrtc_video_engine.cc
index ae366d6..d650f3a 100644
--- a/media/engine/webrtc_video_engine.cc
+++ b/media/engine/webrtc_video_engine.cc
@@ -1895,7 +1895,9 @@
     }
   }
 
-  parameters_.config.rtp.lntf.enabled = HasLntf(codec_settings.codec);
+  const bool has_lntf = HasLntf(codec_settings.codec);
+  parameters_.config.rtp.lntf.enabled = has_lntf;
+  parameters_.config.encoder_settings.capabilities.loss_notification = has_lntf;
 
   parameters_.config.rtp.nack.rtp_history_ms =
       HasNack(codec_settings.codec) ? kNackHistoryMs : 0;
diff --git a/modules/video_coding/codecs/h264/h264_encoder_impl.cc b/modules/video_coding/codecs/h264/h264_encoder_impl.cc
index 2fc1ca9..1cf9dad 100644
--- a/modules/video_coding/codecs/h264/h264_encoder_impl.cc
+++ b/modules/video_coding/codecs/h264/h264_encoder_impl.cc
@@ -191,8 +191,7 @@
 }
 
 int32_t H264EncoderImpl::InitEncode(const VideoCodec* inst,
-                                    int32_t number_of_cores,
-                                    size_t max_payload_size) {
+                                    const VideoEncoder::Settings& settings) {
   ReportInit();
   if (!inst || inst->codecType != kVideoCodecH264) {
     ReportError();
@@ -226,8 +225,8 @@
   pictures_.resize(number_of_streams);
   configurations_.resize(number_of_streams);
 
-  number_of_cores_ = number_of_cores;
-  max_payload_size_ = max_payload_size;
+  number_of_cores_ = settings.number_of_cores;
+  max_payload_size_ = settings.max_payload_size;
   codec_ = *inst;
 
   // Code expects simulcastStream resolutions to be correct, make sure they are
diff --git a/modules/video_coding/codecs/h264/h264_encoder_impl.h b/modules/video_coding/codecs/h264/h264_encoder_impl.h
index 09ca367..6097388 100644
--- a/modules/video_coding/codecs/h264/h264_encoder_impl.h
+++ b/modules/video_coding/codecs/h264/h264_encoder_impl.h
@@ -25,6 +25,7 @@
 #include <vector>
 
 #include "api/video/i420_buffer.h"
+#include "api/video_codecs/video_encoder.h"
 #include "common_video/h264/h264_bitstream_parser.h"
 #include "modules/video_coding/codecs/h264/include/h264.h"
 #include "modules/video_coding/utility/quality_scaler.h"
@@ -56,7 +57,7 @@
   explicit H264EncoderImpl(const cricket::VideoCodec& codec);
   ~H264EncoderImpl() override;
 
-  // |max_payload_size| is ignored.
+  // |settings.max_payload_size| is ignored.
   // The following members of |codec_settings| are used. The rest are ignored.
   // - codecType (must be kVideoCodecH264)
   // - targetBitrate
@@ -64,8 +65,7 @@
   // - width
   // - height
   int32_t InitEncode(const VideoCodec* codec_settings,
-                     int32_t number_of_cores,
-                     size_t max_payload_size) override;
+                     const VideoEncoder::Settings& settings) override;
   int32_t Release() override;
 
   int32_t RegisterEncodeCompleteCallback(
diff --git a/modules/video_coding/codecs/h264/h264_encoder_impl_unittest.cc b/modules/video_coding/codecs/h264/h264_encoder_impl_unittest.cc
index b8b10ae..e81c157 100644
--- a/modules/video_coding/codecs/h264/h264_encoder_impl_unittest.cc
+++ b/modules/video_coding/codecs/h264/h264_encoder_impl_unittest.cc
@@ -11,6 +11,7 @@
 
 #include "modules/video_coding/codecs/h264/h264_encoder_impl.h"
 
+#include "api/video_codecs/video_encoder.h"
 #include "test/gtest.h"
 
 namespace webrtc {
@@ -20,6 +21,11 @@
 const int kMaxPayloadSize = 1024;
 const int kNumCores = 1;
 
+const VideoEncoder::Capabilities kCapabilities(false);
+const VideoEncoder::Settings kSettings(kCapabilities,
+                                       kNumCores,
+                                       kMaxPayloadSize);
+
 void SetDefaultSettings(VideoCodec* codec_settings) {
   codec_settings->codecType = kVideoCodecH264;
   codec_settings->maxFramerate = 60;
@@ -37,7 +43,7 @@
   VideoCodec codec_settings;
   SetDefaultSettings(&codec_settings);
   EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
-            encoder.InitEncode(&codec_settings, kNumCores, kMaxPayloadSize));
+            encoder.InitEncode(&codec_settings, kSettings));
   EXPECT_EQ(H264PacketizationMode::NonInterleaved,
             encoder.PacketizationModeForTesting());
 }
@@ -49,7 +55,7 @@
   VideoCodec codec_settings;
   SetDefaultSettings(&codec_settings);
   EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
-            encoder.InitEncode(&codec_settings, kNumCores, kMaxPayloadSize));
+            encoder.InitEncode(&codec_settings, kSettings));
   EXPECT_EQ(H264PacketizationMode::NonInterleaved,
             encoder.PacketizationModeForTesting());
 }
@@ -61,7 +67,7 @@
   VideoCodec codec_settings;
   SetDefaultSettings(&codec_settings);
   EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
-            encoder.InitEncode(&codec_settings, kNumCores, kMaxPayloadSize));
+            encoder.InitEncode(&codec_settings, kSettings));
   EXPECT_EQ(H264PacketizationMode::SingleNalUnit,
             encoder.PacketizationModeForTesting());
 }
@@ -73,7 +79,7 @@
   VideoCodec codec_settings;
   SetDefaultSettings(&codec_settings);
   EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
-            encoder.InitEncode(&codec_settings, kNumCores, kMaxPayloadSize));
+            encoder.InitEncode(&codec_settings, kSettings));
   EXPECT_EQ(H264PacketizationMode::SingleNalUnit,
             encoder.PacketizationModeForTesting());
 }
diff --git a/modules/video_coding/codecs/multiplex/include/multiplex_encoder_adapter.h b/modules/video_coding/codecs/multiplex/include/multiplex_encoder_adapter.h
index bb00b54..9c17ba4 100644
--- a/modules/video_coding/codecs/multiplex/include/multiplex_encoder_adapter.h
+++ b/modules/video_coding/codecs/multiplex/include/multiplex_encoder_adapter.h
@@ -40,8 +40,7 @@
 
   // Implements VideoEncoder
   int InitEncode(const VideoCodec* inst,
-                 int number_of_cores,
-                 size_t max_payload_size) override;
+                 const VideoEncoder::Settings& settings) override;
   int Encode(const VideoFrame& input_image,
              const std::vector<VideoFrameType>* frame_types) override;
   int RegisterEncodeCompleteCallback(EncodedImageCallback* callback) override;
diff --git a/modules/video_coding/codecs/multiplex/multiplex_encoder_adapter.cc b/modules/video_coding/codecs/multiplex/multiplex_encoder_adapter.cc
index 8c86699..59d59c1 100644
--- a/modules/video_coding/codecs/multiplex/multiplex_encoder_adapter.cc
+++ b/modules/video_coding/codecs/multiplex/multiplex_encoder_adapter.cc
@@ -13,6 +13,7 @@
 #include <cstring>
 
 #include "api/video/encoded_image.h"
+#include "api/video_codecs/video_encoder.h"
 #include "common_video/include/video_frame_buffer.h"
 #include "common_video/libyuv/include/webrtc_libyuv.h"
 #include "modules/include/module_common_types.h"
@@ -60,9 +61,9 @@
   Release();
 }
 
-int MultiplexEncoderAdapter::InitEncode(const VideoCodec* inst,
-                                        int number_of_cores,
-                                        size_t max_payload_size) {
+int MultiplexEncoderAdapter::InitEncode(
+    const VideoCodec* inst,
+    const VideoEncoder::Settings& settings) {
   const size_t buffer_size =
       CalcBufferSize(VideoType::kI420, inst->width, inst->height);
   multiplex_dummy_planes_.resize(buffer_size);
@@ -71,23 +72,23 @@
             0x80);
 
   RTC_DCHECK_EQ(kVideoCodecMultiplex, inst->codecType);
-  VideoCodec settings = *inst;
-  settings.codecType = PayloadStringToCodecType(associated_format_.name);
+  VideoCodec video_codec = *inst;
+  video_codec.codecType = PayloadStringToCodecType(associated_format_.name);
 
   // Take over the key frame interval at adapter level, because we have to
   // sync the key frames for both sub-encoders.
-  switch (settings.codecType) {
+  switch (video_codec.codecType) {
     case kVideoCodecVP8:
-      key_frame_interval_ = settings.VP8()->keyFrameInterval;
-      settings.VP8()->keyFrameInterval = 0;
+      key_frame_interval_ = video_codec.VP8()->keyFrameInterval;
+      video_codec.VP8()->keyFrameInterval = 0;
       break;
     case kVideoCodecVP9:
-      key_frame_interval_ = settings.VP9()->keyFrameInterval;
-      settings.VP9()->keyFrameInterval = 0;
+      key_frame_interval_ = video_codec.VP9()->keyFrameInterval;
+      video_codec.VP9()->keyFrameInterval = 0;
       break;
     case kVideoCodecH264:
-      key_frame_interval_ = settings.H264()->keyFrameInterval;
-      settings.H264()->keyFrameInterval = 0;
+      key_frame_interval_ = video_codec.H264()->keyFrameInterval;
+      video_codec.H264()->keyFrameInterval = 0;
       break;
     default:
       break;
@@ -101,8 +102,7 @@
   for (size_t i = 0; i < kAlphaCodecStreams; ++i) {
     std::unique_ptr<VideoEncoder> encoder =
         factory_->CreateVideoEncoder(associated_format_);
-    const int rv =
-        encoder->InitEncode(&settings, number_of_cores, max_payload_size);
+    const int rv = encoder->InitEncode(&video_codec, settings);
     if (rv) {
       RTC_LOG(LS_ERROR) << "Failed to create multiplex codec index " << i;
       return rv;
diff --git a/modules/video_coding/codecs/test/video_codec_unittest.cc b/modules/video_coding/codecs/test/video_codec_unittest.cc
index b9a911f..bb83903 100644
--- a/modules/video_coding/codecs/test/video_codec_unittest.cc
+++ b/modules/video_coding/codecs/test/video_codec_unittest.cc
@@ -10,6 +10,7 @@
 
 #include <utility>
 
+#include "api/video_codecs/video_encoder.h"
 #include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
 #include "modules/video_coding/codecs/test/video_codec_unittest.h"
 #include "modules/video_coding/include/video_error_codes.h"
@@ -25,6 +26,9 @@
 static const int kMaxFramerate = 30;  // Arbitrary value.
 
 namespace webrtc {
+namespace {
+const VideoEncoder::Capabilities kCapabilities(false);
+}
 
 EncodedImageCallback::Result
 VideoCodecUnitTest::FakeEncodeCompleteCallback::OnEncodedImage(
@@ -78,8 +82,10 @@
   decoder_->RegisterDecodeCompleteCallback(&decode_complete_callback_);
 
   EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
-            encoder_->InitEncode(&codec_settings_, 1 /* number of cores */,
-                                 0 /* max payload size (unused) */));
+            encoder_->InitEncode(
+                &codec_settings_,
+                VideoEncoder::Settings(kCapabilities, 1 /* number of cores */,
+                                       0 /* max payload size (unused) */)));
   EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
             decoder_->InitDecode(&codec_settings_, 1 /* number of cores */));
 }
diff --git a/modules/video_coding/codecs/test/video_encoder_decoder_instantiation_tests.cc b/modules/video_coding/codecs/test/video_encoder_decoder_instantiation_tests.cc
index 6fc898d..e5cce13 100644
--- a/modules/video_coding/codecs/test/video_encoder_decoder_instantiation_tests.cc
+++ b/modules/video_coding/codecs/test/video_encoder_decoder_instantiation_tests.cc
@@ -28,6 +28,7 @@
 namespace test {
 
 namespace {
+const VideoEncoder::Capabilities kCapabilities(false);
 
 int32_t InitEncoder(VideoCodecType codec_type, VideoEncoder* encoder) {
   VideoCodec codec;
@@ -36,8 +37,9 @@
   codec.height = 480;
   codec.maxFramerate = 30;
   RTC_CHECK(encoder);
-  return encoder->InitEncode(&codec, 1 /* number_of_cores */,
-                             1200 /* max_payload_size */);
+  return encoder->InitEncode(
+      &codec, VideoEncoder::Settings(kCapabilities, 1 /* number_of_cores */,
+                                     1200 /* max_payload_size */));
 }
 
 int32_t InitDecoder(VideoCodecType codec_type, VideoDecoder* decoder) {
diff --git a/modules/video_coding/codecs/test/videoprocessor.cc b/modules/video_coding/codecs/test/videoprocessor.cc
index c05729a..d0db139 100644
--- a/modules/video_coding/codecs/test/videoprocessor.cc
+++ b/modules/video_coding/codecs/test/videoprocessor.cc
@@ -24,6 +24,7 @@
 #include "api/video/video_frame_buffer.h"
 #include "api/video/video_rotation.h"
 #include "api/video_codecs/video_codec.h"
+#include "api/video_codecs/video_encoder.h"
 #include "common_video/h264/h264_common.h"
 #include "common_video/libyuv/include/webrtc_libyuv.h"
 #include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
@@ -45,6 +46,8 @@
 const int kMsToRtpTimestamp = kVideoPayloadTypeFrequency / 1000;
 const int kMaxBufferedInputFrames = 20;
 
+const VideoEncoder::Capabilities kCapabilities(false);
+
 size_t GetMaxNaluSizeBytes(const EncodedImage& encoded_frame,
                            const VideoCodecTestFixture::Config& config) {
   if (config.codec_settings.codecType != kVideoCodecH264)
@@ -207,9 +210,11 @@
                WEBRTC_VIDEO_CODEC_OK);
 
   // Initialize codecs so that they are ready to receive frames.
-  RTC_CHECK_EQ(encoder_->InitEncode(&config_.codec_settings,
-                                    static_cast<int>(config_.NumberOfCores()),
-                                    config_.max_payload_size_bytes),
+  RTC_CHECK_EQ(encoder_->InitEncode(
+                   &config_.codec_settings,
+                   VideoEncoder::Settings(
+                       kCapabilities, static_cast<int>(config_.NumberOfCores()),
+                       config_.max_payload_size_bytes)),
                WEBRTC_VIDEO_CODEC_OK);
 
   for (size_t i = 0; i < num_simulcast_or_spatial_layers_; ++i) {
diff --git a/modules/video_coding/codecs/test/videoprocessor_unittest.cc b/modules/video_coding/codecs/test/videoprocessor_unittest.cc
index de1d798..d2b71a7 100644
--- a/modules/video_coding/codecs/test/videoprocessor_unittest.cc
+++ b/modules/video_coding/codecs/test/videoprocessor_unittest.cc
@@ -66,7 +66,7 @@
   }
 
   void ExpectInit() {
-    EXPECT_CALL(encoder_mock_, InitEncode(_, _, _)).Times(1);
+    EXPECT_CALL(encoder_mock_, InitEncode(_, _)).Times(1);
     EXPECT_CALL(encoder_mock_, RegisterEncodeCompleteCallback(_)).Times(1);
     EXPECT_CALL(*decoder_mock_, InitDecode(_, _)).Times(1);
     EXPECT_CALL(*decoder_mock_, RegisterDecodeCompleteCallback(_)).Times(1);
diff --git a/modules/video_coding/codecs/vp8/libvpx_vp8_encoder.cc b/modules/video_coding/codecs/vp8/libvpx_vp8_encoder.cc
index f740b80..06cf870 100644
--- a/modules/video_coding/codecs/vp8/libvpx_vp8_encoder.cc
+++ b/modules/video_coding/codecs/vp8/libvpx_vp8_encoder.cc
@@ -450,9 +450,10 @@
   send_stream_[stream_idx] = send_stream;
 }
 
+// TODO(eladalon): s/inst/codec_settings/g.
+// TODO(bugs.webrtc.org/10720): Pass |capabilities| to frame buffer controller.
 int LibvpxVp8Encoder::InitEncode(const VideoCodec* inst,
-                                 int number_of_cores,
-                                 size_t /*maxPayloadSize */) {
+                                 const VideoEncoder::Settings& settings) {
   if (inst == NULL) {
     return WEBRTC_VIDEO_CODEC_ERR_PARAMETER;
   }
@@ -466,7 +467,7 @@
   if (inst->width < 1 || inst->height < 1) {
     return WEBRTC_VIDEO_CODEC_ERR_PARAMETER;
   }
-  if (number_of_cores < 1) {
+  if (settings.number_of_cores < 1) {
     return WEBRTC_VIDEO_CODEC_ERR_PARAMETER;
   }
   if (inst->VP8().automaticResizeOn && inst->numberOfSimulcastStreams > 1) {
@@ -492,7 +493,7 @@
   }
   RTC_DCHECK(frame_buffer_controller_);
 
-  number_of_cores_ = number_of_cores;
+  number_of_cores_ = settings.number_of_cores;
   timestamp_ = 0;
   codec_ = *inst;
 
@@ -611,7 +612,7 @@
   // Determine number of threads based on the image size and #cores.
   // TODO(fbarchard): Consider number of Simulcast layers.
   vpx_configs_[0].g_threads = NumberOfThreads(
-      vpx_configs_[0].g_w, vpx_configs_[0].g_h, number_of_cores);
+      vpx_configs_[0].g_w, vpx_configs_[0].g_h, settings.number_of_cores);
 
   // Creating a wrapper to the image - setting image data to NULL.
   // Actual pointer will be set in encode. Setting align to 1, as it
diff --git a/modules/video_coding/codecs/vp8/libvpx_vp8_encoder.h b/modules/video_coding/codecs/vp8/libvpx_vp8_encoder.h
index 214b969..9053207 100644
--- a/modules/video_coding/codecs/vp8/libvpx_vp8_encoder.h
+++ b/modules/video_coding/codecs/vp8/libvpx_vp8_encoder.h
@@ -46,8 +46,7 @@
   int Release() override;
 
   int InitEncode(const VideoCodec* codec_settings,
-                 int number_of_cores,
-                 size_t max_payload_size) override;
+                 const VideoEncoder::Settings& settings) override;
 
   int Encode(const VideoFrame& input_image,
              const std::vector<VideoFrameType>* frame_types) override;
diff --git a/modules/video_coding/codecs/vp8/test/vp8_impl_unittest.cc b/modules/video_coding/codecs/vp8/test/vp8_impl_unittest.cc
index eb6b89f..b5e11f4 100644
--- a/modules/video_coding/codecs/vp8/test/vp8_impl_unittest.cc
+++ b/modules/video_coding/codecs/vp8/test/vp8_impl_unittest.cc
@@ -14,6 +14,7 @@
 
 #include "api/test/mock_video_decoder.h"
 #include "api/test/mock_video_encoder.h"
+#include "api/video_codecs/video_encoder.h"
 #include "api/video_codecs/vp8_temporal_layers.h"
 #include "common_video/libyuv/include/webrtc_libyuv.h"
 #include "common_video/test/utilities.h"
@@ -51,6 +52,11 @@
 constexpr int kWidth = 172;
 constexpr int kHeight = 144;
 constexpr float kFramerateFps = 30;
+
+const VideoEncoder::Capabilities kCapabilities(false);
+const VideoEncoder::Settings kSettings(kCapabilities,
+                                       kNumCores,
+                                       kMaxPayloadSize);
 }  // namespace
 
 class TestVp8Impl : public VideoCodecUnitTest {
@@ -117,7 +123,8 @@
   auto* const vpx = new NiceMock<MockLibvpxVp8Interface>();
   LibvpxVp8Encoder encoder((std::unique_ptr<LibvpxInterface>(vpx)));
   EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
-            encoder.InitEncode(&codec_settings_, 1, 1000));
+            encoder.InitEncode(&codec_settings_,
+                               VideoEncoder::Settings(kCapabilities, 1, 1000)));
 
   const uint32_t kBitrateBps = 300000;
   VideoBitrateAllocation bitrate_allocation;
@@ -143,7 +150,8 @@
   auto* const vpx = new NiceMock<MockLibvpxVp8Interface>();
   LibvpxVp8Encoder encoder((std::unique_ptr<LibvpxInterface>(vpx)));
   EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
-            encoder.InitEncode(&codec_settings_, 1, 1000));
+            encoder.InitEncode(&codec_settings_,
+                               VideoEncoder::Settings(kCapabilities, 1, 1000)));
 
   const uint32_t kBitrateBps = 300000;
   VideoEncoder::RateControlParameters rate_settings;
@@ -199,7 +207,7 @@
 TEST_F(TestVp8Impl, EncodeFrameAndRelease) {
   EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, encoder_->Release());
   EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
-            encoder_->InitEncode(&codec_settings_, kNumCores, kMaxPayloadSize));
+            encoder_->InitEncode(&codec_settings_, kSettings));
 
   EncodedImage encoded_frame;
   CodecSpecificInfo codec_specific_info;
@@ -257,7 +265,7 @@
   codec_settings_.simulcastStream[1] = {kWidth / 2, kHeight / 2, 30,   3,
                                         4000,       3000,        2000, 80};
   EXPECT_EQ(WEBRTC_VIDEO_CODEC_ERR_SIMULCAST_PARAMETERS_NOT_SUPPORTED,
-            encoder_->InitEncode(&codec_settings_, kNumCores, kMaxPayloadSize));
+            encoder_->InitEncode(&codec_settings_, kSettings));
   codec_settings_.numberOfSimulcastStreams = 3;
   // Resolutions are not in ascending order.
   codec_settings_.simulcastStream[0] = {
@@ -267,7 +275,7 @@
   codec_settings_.simulcastStream[2] = {kWidth, kHeight, 30,   1,
                                         4000,   3000,    2000, 80};
   EXPECT_EQ(WEBRTC_VIDEO_CODEC_ERR_SIMULCAST_PARAMETERS_NOT_SUPPORTED,
-            encoder_->InitEncode(&codec_settings_, kNumCores, kMaxPayloadSize));
+            encoder_->InitEncode(&codec_settings_, kSettings));
   // Resolutions are not in ascending order.
   codec_settings_.simulcastStream[0] = {kWidth, kHeight, kFramerateFps, 1,
                                         4000,   3000,    2000,          80};
@@ -276,7 +284,7 @@
   codec_settings_.simulcastStream[2] = {
       kWidth - 1, kHeight - 1, kFramerateFps, 1, 4000, 3000, 2000, 80};
   EXPECT_EQ(WEBRTC_VIDEO_CODEC_ERR_SIMULCAST_PARAMETERS_NOT_SUPPORTED,
-            encoder_->InitEncode(&codec_settings_, kNumCores, kMaxPayloadSize));
+            encoder_->InitEncode(&codec_settings_, kSettings));
   // Temporal layers do not match.
   codec_settings_.simulcastStream[0] = {
       kWidth / 4, kHeight / 4, kFramerateFps, 1, 4000, 3000, 2000, 80};
@@ -285,7 +293,7 @@
   codec_settings_.simulcastStream[2] = {kWidth, kHeight, kFramerateFps, 3,
                                         4000,   3000,    2000,          80};
   EXPECT_EQ(WEBRTC_VIDEO_CODEC_ERR_SIMULCAST_PARAMETERS_NOT_SUPPORTED,
-            encoder_->InitEncode(&codec_settings_, kNumCores, kMaxPayloadSize));
+            encoder_->InitEncode(&codec_settings_, kSettings));
   // Resolutions do not match codec config.
   codec_settings_.simulcastStream[0] = {
       kWidth / 4 + 1, kHeight / 4 + 1, kFramerateFps, 1, 4000, 3000, 2000, 80};
@@ -294,7 +302,7 @@
   codec_settings_.simulcastStream[2] = {
       kWidth + 4, kHeight + 4, kFramerateFps, 1, 4000, 3000, 2000, 80};
   EXPECT_EQ(WEBRTC_VIDEO_CODEC_ERR_SIMULCAST_PARAMETERS_NOT_SUPPORTED,
-            encoder_->InitEncode(&codec_settings_, kNumCores, kMaxPayloadSize));
+            encoder_->InitEncode(&codec_settings_, kSettings));
   // Everything fine: scaling by 2, top resolution matches video, temporal
   // settings are the same for all layers.
   codec_settings_.simulcastStream[0] = {
@@ -304,7 +312,7 @@
   codec_settings_.simulcastStream[2] = {kWidth, kHeight, kFramerateFps, 1,
                                         4000,   3000,    2000,          80};
   EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
-            encoder_->InitEncode(&codec_settings_, kNumCores, kMaxPayloadSize));
+            encoder_->InitEncode(&codec_settings_, kSettings));
   // Everything fine: custom scaling, top resolution matches video, temporal
   // settings are the same for all layers.
   codec_settings_.simulcastStream[0] = {
@@ -314,7 +322,7 @@
   codec_settings_.simulcastStream[2] = {kWidth, kHeight, kFramerateFps, 1,
                                         4000,   3000,    2000,          80};
   EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
-            encoder_->InitEncode(&codec_settings_, kNumCores, kMaxPayloadSize));
+            encoder_->InitEncode(&codec_settings_, kSettings));
 }
 
 #if defined(WEBRTC_ANDROID)
@@ -378,7 +386,7 @@
 TEST_F(TestVp8Impl, EncoderWith2TemporalLayers) {
   codec_settings_.VP8()->numberOfTemporalLayers = 2;
   EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
-            encoder_->InitEncode(&codec_settings_, kNumCores, kMaxPayloadSize));
+            encoder_->InitEncode(&codec_settings_, kSettings));
 
   // Temporal layer 0.
   EncodedImage encoded_frame;
@@ -399,7 +407,7 @@
   codec_settings_.VP8()->frameDroppingOn = true;
   codec_settings_.VP8()->automaticResizeOn = false;
   EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
-            encoder_->InitEncode(&codec_settings_, kNumCores, kMaxPayloadSize));
+            encoder_->InitEncode(&codec_settings_, kSettings));
 
   VideoEncoder::ScalingSettings settings =
       encoder_->GetEncoderInfo().scaling_settings;
@@ -410,7 +418,7 @@
   codec_settings_.VP8()->frameDroppingOn = true;
   codec_settings_.VP8()->automaticResizeOn = true;
   EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
-            encoder_->InitEncode(&codec_settings_, kNumCores, kMaxPayloadSize));
+            encoder_->InitEncode(&codec_settings_, kSettings));
 
   VideoEncoder::ScalingSettings settings =
       encoder_->GetEncoderInfo().scaling_settings;
@@ -442,7 +450,7 @@
       /* num_squares = */ absl::optional<int>(300));
 
   EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
-            encoder_->InitEncode(&codec_settings_, kNumCores, kMaxPayloadSize));
+            encoder_->InitEncode(&codec_settings_, kSettings));
 
   VideoBitrateAllocation bitrate_allocation;
   // Bitrate only enough for TL0.
@@ -480,7 +488,8 @@
         return img;
       }));
   EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
-            encoder.InitEncode(&codec_settings_, 1, 1000));
+            encoder.InitEncode(&codec_settings_,
+                               VideoEncoder::Settings(kCapabilities, 1, 1000)));
   MockEncodedImageCallback callback;
   encoder.RegisterEncodeCompleteCallback(&callback);
 
@@ -512,7 +521,7 @@
   codec_settings_.simulcastStream[0].maxBitrate = 100;
   codec_settings_.simulcastStream[0].numberOfTemporalLayers = 2;
   EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
-            encoder_->InitEncode(&codec_settings_, kNumCores, kMaxPayloadSize));
+            encoder_->InitEncode(&codec_settings_, kSettings));
 
   FramerateFractions expected_fps_allocation[kMaxSpatialLayers];
   expected_fps_allocation[0].push_back(EncoderInfo::kMaxFramerateFraction / 2);
@@ -530,7 +539,7 @@
   codec_settings_.simulcastStream[0].maxBitrate = 100;
   codec_settings_.simulcastStream[0].numberOfTemporalLayers = 3;
   EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
-            encoder_->InitEncode(&codec_settings_, kNumCores, kMaxPayloadSize));
+            encoder_->InitEncode(&codec_settings_, kSettings));
 
   FramerateFractions expected_fps_allocation[kMaxSpatialLayers];
   expected_fps_allocation[0].push_back(EncoderInfo::kMaxFramerateFraction / 4);
@@ -553,7 +562,7 @@
       kLegacyScreenshareTl1BitrateKbps;
   codec_settings_.simulcastStream[0].numberOfTemporalLayers = 2;
   EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
-            encoder_->InitEncode(&codec_settings_, kNumCores, kMaxPayloadSize));
+            encoder_->InitEncode(&codec_settings_, kSettings));
 
   // Expect empty vector, since this mode doesn't have a fixed framerate.
   FramerateFractions expected_fps_allocation[kMaxSpatialLayers];
@@ -581,7 +590,7 @@
   }
 
   EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
-            encoder_->InitEncode(&codec_settings_, kNumCores, kMaxPayloadSize));
+            encoder_->InitEncode(&codec_settings_, kSettings));
 
   FramerateFractions expected_fps_allocation[kMaxSpatialLayers];
   expected_fps_allocation[0].push_back(EncoderInfo::kMaxFramerateFraction / 4);
diff --git a/modules/video_coding/codecs/vp9/test/vp9_impl_unittest.cc b/modules/video_coding/codecs/vp9/test/vp9_impl_unittest.cc
index d806239..ae509a6 100644
--- a/modules/video_coding/codecs/vp9/test/vp9_impl_unittest.cc
+++ b/modules/video_coding/codecs/vp9/test/vp9_impl_unittest.cc
@@ -10,6 +10,7 @@
 
 #include "api/video/color_space.h"
 #include "api/video/i420_buffer.h"
+#include "api/video_codecs/video_encoder.h"
 #include "common_video/libyuv/include/webrtc_libyuv.h"
 #include "media/base/vp9_profile.h"
 #include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
@@ -31,6 +32,11 @@
 namespace {
 const size_t kWidth = 1280;
 const size_t kHeight = 720;
+
+const VideoEncoder::Capabilities kCapabilities(false);
+const VideoEncoder::Settings kSettings(kCapabilities,
+                                       /*number_of_cores=*/1,
+                                       /*max_payload_size=*/0);
 }  // namespace
 
 class TestVp9Impl : public VideoCodecUnitTest {
@@ -199,8 +205,7 @@
   // Tl0PidIdx is only used in non-flexible mode.
   codec_settings_.VP9()->flexibleMode = false;
   EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
-            encoder_->InitEncode(&codec_settings_, 1 /* number of cores */,
-                                 0 /* max payload size (unused) */));
+            encoder_->InitEncode(&codec_settings_, kSettings));
 
   // Temporal layer 0.
   EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
@@ -229,8 +234,7 @@
 TEST_F(TestVp9Impl, EncoderWith2SpatialLayers) {
   codec_settings_.VP9()->numberOfSpatialLayers = 2;
   EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
-            encoder_->InitEncode(&codec_settings_, 1 /* number of cores */,
-                                 0 /* max payload size (unused) */));
+            encoder_->InitEncode(&codec_settings_, kSettings));
 
   SetWaitForEncodedFramesThreshold(2);
   EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
@@ -273,8 +277,7 @@
   codec_settings_.spatialLayers[1].maxFramerate = codec_settings_.maxFramerate;
 
   EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
-            encoder_->InitEncode(&codec_settings_, 1 /* number of cores */,
-                                 0 /* max payload size (unused) */));
+            encoder_->InitEncode(&codec_settings_, kSettings));
 
   // Ensure it fails if scaling factors in horz/vert dimentions are different.
   codec_settings_.spatialLayers[0].width = codec_settings_.width;
@@ -282,8 +285,7 @@
   codec_settings_.spatialLayers[1].width = codec_settings_.width;
   codec_settings_.spatialLayers[1].height = codec_settings_.height;
   EXPECT_EQ(WEBRTC_VIDEO_CODEC_ERR_PARAMETER,
-            encoder_->InitEncode(&codec_settings_, 1 /* number of cores */,
-                                 0 /* max payload size (unused) */));
+            encoder_->InitEncode(&codec_settings_, kSettings));
 
   // Ensure it fails if scaling factor is not power of two.
   codec_settings_.spatialLayers[0].width = codec_settings_.width / 3;
@@ -291,8 +293,7 @@
   codec_settings_.spatialLayers[1].width = codec_settings_.width;
   codec_settings_.spatialLayers[1].height = codec_settings_.height;
   EXPECT_EQ(WEBRTC_VIDEO_CODEC_ERR_PARAMETER,
-            encoder_->InitEncode(&codec_settings_, 1 /* number of cores */,
-                                 0 /* max payload size (unused) */));
+            encoder_->InitEncode(&codec_settings_, kSettings));
 }
 
 TEST_F(TestVp9Impl, EnableDisableSpatialLayers) {
@@ -309,8 +310,7 @@
   codec_settings_.VP9()->frameDroppingOn = true;
 
   EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
-            encoder_->InitEncode(&codec_settings_, 1 /* number of cores */,
-                                 0 /* max payload size (unused) */));
+            encoder_->InitEncode(&codec_settings_, kSettings));
 
   VideoBitrateAllocation bitrate_allocation;
   for (size_t sl_idx = 0; sl_idx < num_spatial_layers; ++sl_idx) {
@@ -357,8 +357,7 @@
   ConfigureSvc(num_spatial_layers);
 
   EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
-            encoder_->InitEncode(&codec_settings_, 1 /* number of cores */,
-                                 0 /* max payload size (unused) */));
+            encoder_->InitEncode(&codec_settings_, kSettings));
 
   // Encode both base and upper layers. Check that end-of-superframe flag is
   // set on upper layer frame but not on base layer frame.
@@ -385,8 +384,7 @@
   encoder_->SetRates(VideoEncoder::RateControlParameters(
       bitrate_allocation, codec_settings_.maxFramerate));
   EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
-            encoder_->InitEncode(&codec_settings_, 1 /* number of cores */,
-                                 0 /* max payload size (unused) */));
+            encoder_->InitEncode(&codec_settings_, kSettings));
 
   SetWaitForEncodedFramesThreshold(1);
   EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
@@ -415,8 +413,7 @@
   for (const InterLayerPredMode inter_layer_pred : inter_layer_pred_modes) {
     codec_settings_.VP9()->interLayerPred = inter_layer_pred;
     EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
-              encoder_->InitEncode(&codec_settings_, 1 /* number of cores */,
-                                   0 /* max payload size (unused) */));
+              encoder_->InitEncode(&codec_settings_, kSettings));
 
     encoder_->SetRates(VideoEncoder::RateControlParameters(
         bitrate_allocation, codec_settings_.maxFramerate));
@@ -485,8 +482,7 @@
   for (const InterLayerPredMode inter_layer_pred : inter_layer_pred_modes) {
     codec_settings_.VP9()->interLayerPred = inter_layer_pred;
     EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
-              encoder_->InitEncode(&codec_settings_, 1 /* number of cores */,
-                                   0 /* max payload size (unused) */));
+              encoder_->InitEncode(&codec_settings_, kSettings));
 
     VideoBitrateAllocation bitrate_allocation;
     for (size_t sl_idx = 0; sl_idx < num_spatial_layers; ++sl_idx) {
@@ -544,8 +540,7 @@
   for (const InterLayerPredMode inter_layer_pred : inter_layer_pred_modes) {
     codec_settings_.VP9()->interLayerPred = inter_layer_pred;
     EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
-              encoder_->InitEncode(&codec_settings_, 1 /* number of cores */,
-                                   0 /* max payload size (unused) */));
+              encoder_->InitEncode(&codec_settings_, kSettings));
 
     VideoBitrateAllocation bitrate_allocation;
     for (size_t sl_idx = 0; sl_idx < num_spatial_layers; ++sl_idx) {
@@ -595,8 +590,7 @@
 
   codec_settings_.VP9()->interLayerPred = InterLayerPredMode::kOn;
   EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
-            encoder_->InitEncode(&codec_settings_, 1 /* number of cores */,
-                                 0 /* max payload size (unused) */));
+            encoder_->InitEncode(&codec_settings_, kSettings));
 
   VideoBitrateAllocation bitrate_allocation;
 
@@ -670,8 +664,7 @@
 
   codec_settings_.VP9()->interLayerPred = InterLayerPredMode::kOn;
   EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
-            encoder_->InitEncode(&codec_settings_, 1 /* number of cores */,
-                                 0 /* max payload size (unused) */));
+            encoder_->InitEncode(&codec_settings_, kSettings));
 
   VideoBitrateAllocation bitrate_allocation;
 
@@ -761,8 +754,7 @@
   codec_settings_.VP9()->interLayerPred = InterLayerPredMode::kOn;
   codec_settings_.VP9()->flexibleMode = true;
   EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
-            encoder_->InitEncode(&codec_settings_, 1 /* number of cores */,
-                                 0 /* max payload size (unused) */));
+            encoder_->InitEncode(&codec_settings_, kSettings));
 
   // Enable all but the last layer.
   VideoBitrateAllocation bitrate_allocation;
@@ -830,8 +822,7 @@
   codec_settings_.VP9()->interLayerPred = InterLayerPredMode::kOn;
   codec_settings_.VP9()->flexibleMode = true;
   EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
-            encoder_->InitEncode(&codec_settings_, 1 /* number of cores */,
-                                 0 /* max payload size (unused) */));
+            encoder_->InitEncode(&codec_settings_, kSettings));
 
   // Enable all but the last layer.
   VideoBitrateAllocation bitrate_allocation;
@@ -924,8 +915,7 @@
   codec_settings_.VP9()->interLayerPred = InterLayerPredMode::kOn;
   codec_settings_.VP9()->flexibleMode = true;
   EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
-            encoder_->InitEncode(&codec_settings_, 1 /* number of cores */,
-                                 0 /* max payload size (unused) */));
+            encoder_->InitEncode(&codec_settings_, kSettings));
 
   // All layers are enabled from the start.
   VideoBitrateAllocation bitrate_allocation;
@@ -1007,8 +997,7 @@
   codec_settings_.VP9()->interLayerPred = InterLayerPredMode::kOnKeyPic;
   codec_settings_.VP9()->flexibleMode = false;
   EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
-            encoder_->InitEncode(&codec_settings_, 1 /* number of cores */,
-                                 0 /* max payload size (unused) */));
+            encoder_->InitEncode(&codec_settings_, kSettings));
 
   // Enable all the layers.
   VideoBitrateAllocation bitrate_allocation;
@@ -1069,8 +1058,7 @@
   codec_settings_.VP9()->interLayerPred = InterLayerPredMode::kOn;
 
   EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
-            encoder_->InitEncode(&codec_settings_, 1 /* number of cores */,
-                                 0 /* max payload size (unused) */));
+            encoder_->InitEncode(&codec_settings_, kSettings));
 
   VideoBitrateAllocation bitrate_allocation;
   bitrate_allocation.SetBitrate(
@@ -1089,8 +1077,7 @@
 TEST_F(TestVp9Impl, ScalabilityStructureIsAvailableInFlexibleMode) {
   codec_settings_.VP9()->flexibleMode = true;
   EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
-            encoder_->InitEncode(&codec_settings_, 1 /* number of cores */,
-                                 0 /* max payload size (unused) */));
+            encoder_->InitEncode(&codec_settings_, kSettings));
 
   EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
             encoder_->Encode(*NextInputFrame(), nullptr));
@@ -1123,8 +1110,7 @@
   }
 
   EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
-            encoder_->InitEncode(&codec_settings_, 1 /* number of cores */,
-                                 0 /* max payload size (unused) */));
+            encoder_->InitEncode(&codec_settings_, kSettings));
 
   FramerateFractions expected_fps_allocation[kMaxSpatialLayers];
   expected_fps_allocation[0].push_back(EncoderInfo::kMaxFramerateFraction / 4);
@@ -1161,8 +1147,7 @@
   }
 
   EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
-            encoder_->InitEncode(&codec_settings_, 1 /* number of cores */,
-                                 0 /* max payload size (unused) */));
+            encoder_->InitEncode(&codec_settings_, kSettings));
 
   // No temporal layers allowed when spatial layers have different fps targets.
   FramerateFractions expected_fps_allocation[kMaxSpatialLayers];
@@ -1195,8 +1180,7 @@
   codec_settings_.VP9()->numberOfSpatialLayers = num_spatial_layers_;
   codec_settings_.VP9()->numberOfTemporalLayers = num_temporal_layers_;
   EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
-            encoder_->InitEncode(&codec_settings_, 1 /* number of cores */,
-                                 0 /* max payload size (unused) */));
+            encoder_->InitEncode(&codec_settings_, kSettings));
 
   GofInfoVP9 gof;
   if (num_temporal_layers_ == 1) {
@@ -1234,8 +1218,7 @@
   codec_settings_.VP9()->numberOfSpatialLayers = num_spatial_layers_;
   codec_settings_.VP9()->numberOfTemporalLayers = num_temporal_layers_;
   EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
-            encoder_->InitEncode(&codec_settings_, 1 /* number of cores */,
-                                 0 /* max payload size (unused) */));
+            encoder_->InitEncode(&codec_settings_, kSettings));
 
   GofInfoVP9 gof;
   if (num_temporal_layers_ == 1) {
@@ -1291,8 +1274,7 @@
 
   codec_settings_.maxFramerate = static_cast<uint32_t>(expected_framerate_fps);
   EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
-            encoder_->InitEncode(&codec_settings_, 1 /* number of cores */,
-                                 0 /* max payload size (unused) */));
+            encoder_->InitEncode(&codec_settings_, kSettings));
 
   VideoFrame* input_frame = NextInputFrame();
   for (size_t frame_num = 0; frame_num < num_frames_to_encode; ++frame_num) {
@@ -1341,8 +1323,7 @@
   }
 
   EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
-            encoder_->InitEncode(&codec_settings_, 1 /* number of cores */,
-                                 0 /* max payload size (unused) */));
+            encoder_->InitEncode(&codec_settings_, kSettings));
 
   encoder_->SetRates(VideoEncoder::RateControlParameters(
       bitrate_allocation, codec_settings_.maxFramerate));
diff --git a/modules/video_coding/codecs/vp9/vp9_impl.cc b/modules/video_coding/codecs/vp9/vp9_impl.cc
index 18acf02..d81c615 100644
--- a/modules/video_coding/codecs/vp9/vp9_impl.cc
+++ b/modules/video_coding/codecs/vp9/vp9_impl.cc
@@ -401,9 +401,9 @@
   return;
 }
 
+// TODO(eladalon): s/inst/codec_settings/g.
 int VP9EncoderImpl::InitEncode(const VideoCodec* inst,
-                               int number_of_cores,
-                               size_t /*max_payload_size*/) {
+                               const Settings& settings) {
   if (inst == nullptr) {
     return WEBRTC_VIDEO_CODEC_ERR_PARAMETER;
   }
@@ -417,7 +417,7 @@
   if (inst->width < 1 || inst->height < 1) {
     return WEBRTC_VIDEO_CODEC_ERR_PARAMETER;
   }
-  if (number_of_cores < 1) {
+  if (settings.number_of_cores < 1) {
     return WEBRTC_VIDEO_CODEC_ERR_PARAMETER;
   }
   if (inst->VP9().numberOfTemporalLayers > 3) {
@@ -526,7 +526,7 @@
   config_->rc_resize_allowed = inst->VP9().automaticResizeOn ? 1 : 0;
   // Determine number of threads based on the image size and #cores.
   config_->g_threads =
-      NumberOfThreads(config_->g_w, config_->g_h, number_of_cores);
+      NumberOfThreads(config_->g_w, config_->g_h, settings.number_of_cores);
 
   cpu_speed_ = GetCpuSpeed(config_->g_w, config_->g_h);
 
diff --git a/modules/video_coding/codecs/vp9/vp9_impl.h b/modules/video_coding/codecs/vp9/vp9_impl.h
index f58fc34..7ceb699 100644
--- a/modules/video_coding/codecs/vp9/vp9_impl.h
+++ b/modules/video_coding/codecs/vp9/vp9_impl.h
@@ -21,6 +21,7 @@
 
 #include "modules/video_coding/codecs/vp9/include/vp9.h"
 
+#include "api/video_codecs/video_encoder.h"
 #include "media/base/vp9_profile.h"
 #include "modules/video_coding/codecs/vp9/vp9_frame_buffer_pool.h"
 #include "modules/video_coding/utility/framerate_controller.h"
@@ -40,8 +41,7 @@
   int Release() override;
 
   int InitEncode(const VideoCodec* codec_settings,
-                 int number_of_cores,
-                 size_t max_payload_size) override;
+                 const Settings& settings) override;
 
   int Encode(const VideoFrame& input_image,
              const std::vector<VideoFrameType>* frame_types) override;
diff --git a/modules/video_coding/utility/simulcast_test_fixture_impl.cc b/modules/video_coding/utility/simulcast_test_fixture_impl.cc
index 91e5508..eadb5a2 100644
--- a/modules/video_coding/utility/simulcast_test_fixture_impl.cc
+++ b/modules/video_coding/utility/simulcast_test_fixture_impl.cc
@@ -18,6 +18,7 @@
 #include "absl/memory/memory.h"
 #include "api/video/encoded_image.h"
 #include "api/video_codecs/sdp_video_format.h"
+#include "api/video_codecs/video_encoder.h"
 #include "common_video/libyuv/include/webrtc_libyuv.h"
 #include "modules/video_coding/include/video_codec_interface.h"
 #include "modules/video_coding/include/video_coding_defines.h"
@@ -46,6 +47,9 @@
 const int kDefaultTemporalLayerProfile[3] = {3, 3, 3};
 const int kNoTemporalLayerProfile[3] = {0, 0, 0};
 
+const VideoEncoder::Capabilities kCapabilities(false);
+const VideoEncoder::Settings kSettings(kCapabilities, 1, 1200);
+
 template <typename T>
 void SetExpectedValues3(T value0, T value1, T value2, T* expected_values) {
   expected_values[0] = value0;
@@ -271,7 +275,7 @@
   decoder_->RegisterDecodeCompleteCallback(&decoder_callback_);
   DefaultSettings(&settings_, temporal_layer_profile, codec_type_);
   SetUpRateAllocator();
-  EXPECT_EQ(0, encoder_->InitEncode(&settings_, 1, 1200));
+  EXPECT_EQ(0, encoder_->InitEncode(&settings_, kSettings));
   EXPECT_EQ(0, decoder_->InitDecode(&settings_, 1));
   input_buffer_ = I420Buffer::Create(kDefaultWidth, kDefaultHeight);
   input_buffer_->InitializeData();
@@ -323,7 +327,7 @@
   // allocator has support for updating active streams without a
   // reinitialization, we can just call that here instead.
   SetUpRateAllocator();
-  EXPECT_EQ(0, encoder_->InitEncode(&settings_, 1, 1200));
+  EXPECT_EQ(0, encoder_->InitEncode(&settings_, kSettings));
 }
 
 void SimulcastTestFixtureImpl::ExpectStreams(
@@ -617,7 +621,7 @@
   settings_.simulcastStream[settings_.numberOfSimulcastStreams - 1].height =
       settings_.height;
   SetUpRateAllocator();
-  EXPECT_EQ(0, encoder_->InitEncode(&settings_, 1, 1200));
+  EXPECT_EQ(0, encoder_->InitEncode(&settings_, kSettings));
 
   // Encode one frame and verify.
   SetRates(kMaxBitrates[0] + kMaxBitrates[1], 30);
@@ -640,7 +644,7 @@
   // Start at the lowest bitrate for enabling base stream.
   settings_.startBitrate = kMinBitrates[0];
   SetUpRateAllocator();
-  EXPECT_EQ(0, encoder_->InitEncode(&settings_, 1, 1200));
+  EXPECT_EQ(0, encoder_->InitEncode(&settings_, kSettings));
   SetRates(settings_.startBitrate, 30);
   ExpectStreams(VideoFrameType::kVideoFrameKey, 1);
   // Resize |input_frame_| to the new resolution.
diff --git a/sdk/android/BUILD.gn b/sdk/android/BUILD.gn
index 187f885..8ffc959 100644
--- a/sdk/android/BUILD.gn
+++ b/sdk/android/BUILD.gn
@@ -710,6 +710,7 @@
       "../../rtc_base:checks",
       "../../rtc_base:rtc_task_queue",
       "../../rtc_base/task_utils:to_queued_task",
+      "//third_party/abseil-cpp/absl/types:optional",
       "//third_party/libyuv",
     ]
   }
diff --git a/sdk/android/api/org/webrtc/VideoEncoder.java b/sdk/android/api/org/webrtc/VideoEncoder.java
index b37f5aa..a5b2c4d 100644
--- a/sdk/android/api/org/webrtc/VideoEncoder.java
+++ b/sdk/android/api/org/webrtc/VideoEncoder.java
@@ -28,10 +28,19 @@
     public final int maxFramerate;
     public final int numberOfSimulcastStreams;
     public final boolean automaticResizeOn;
+    public final Capabilities capabilities;
+
+    // TODO(bugs.webrtc.org/10720): Remove.
+    @Deprecated
+    public Settings(int numberOfCores, int width, int height, int startBitrate, int maxFramerate,
+        int numberOfSimulcastStreams, boolean automaticResizeOn) {
+      this(numberOfCores, width, height, startBitrate, maxFramerate, numberOfSimulcastStreams,
+          automaticResizeOn, new VideoEncoder.Capabilities(false /* lossNotification */));
+    }
 
     @CalledByNative("Settings")
     public Settings(int numberOfCores, int width, int height, int startBitrate, int maxFramerate,
-        int numberOfSimulcastStreams, boolean automaticResizeOn) {
+        int numberOfSimulcastStreams, boolean automaticResizeOn, Capabilities capabilities) {
       this.numberOfCores = numberOfCores;
       this.width = width;
       this.height = height;
@@ -39,6 +48,21 @@
       this.maxFramerate = maxFramerate;
       this.numberOfSimulcastStreams = numberOfSimulcastStreams;
       this.automaticResizeOn = automaticResizeOn;
+      this.capabilities = capabilities;
+    }
+  }
+
+  /** Capabilities (loss notification, etc.) passed to the encoder by WebRTC. */
+  public class Capabilities {
+    /**
+     * The remote side has support for the loss notification RTCP feedback message format, and will
+     * be sending these feedback messages if necessary.
+     */
+    public final boolean lossNotification;
+
+    @CalledByNative("Capabilities")
+    public Capabilities(boolean lossNotification) {
+      this.lossNotification = lossNotification;
     }
   }
 
diff --git a/sdk/android/instrumentationtests/src/org/webrtc/AndroidVideoDecoderInstrumentationTest.java b/sdk/android/instrumentationtests/src/org/webrtc/AndroidVideoDecoderInstrumentationTest.java
index 211b93a..723012b 100644
--- a/sdk/android/instrumentationtests/src/org/webrtc/AndroidVideoDecoderInstrumentationTest.java
+++ b/sdk/android/instrumentationtests/src/org/webrtc/AndroidVideoDecoderInstrumentationTest.java
@@ -76,7 +76,8 @@
   private static final boolean ENABLE_H264_HIGH_PROFILE = true;
   private static final VideoEncoder.Settings ENCODER_SETTINGS =
       new VideoEncoder.Settings(1 /* core */, TEST_FRAME_WIDTH, TEST_FRAME_HEIGHT, 300 /* kbps */,
-          30 /* fps */, 1 /* numberOfSimulcastStreams */, true /* automaticResizeOn */);
+          30 /* fps */, 1 /* numberOfSimulcastStreams */, true /* automaticResizeOn */,
+          /* capabilities= */ new VideoEncoder.Capabilities(false /* lossNotification */));
 
   private static final int DECODE_TIMEOUT_MS = 1000;
   private static final VideoDecoder.Settings SETTINGS =
diff --git a/sdk/android/instrumentationtests/src/org/webrtc/HardwareVideoEncoderTest.java b/sdk/android/instrumentationtests/src/org/webrtc/HardwareVideoEncoderTest.java
index 8c75878..639c54d 100644
--- a/sdk/android/instrumentationtests/src/org/webrtc/HardwareVideoEncoderTest.java
+++ b/sdk/android/instrumentationtests/src/org/webrtc/HardwareVideoEncoderTest.java
@@ -70,7 +70,8 @@
   private static final boolean ENABLE_H264_HIGH_PROFILE = true;
   private static final VideoEncoder.Settings SETTINGS =
       new VideoEncoder.Settings(1 /* core */, 640 /* width */, 480 /* height */, 300 /* kbps */,
-          30 /* fps */, 1 /* numberOfSimulcastStreams */, true /* automaticResizeOn */);
+          30 /* fps */, 1 /* numberOfSimulcastStreams */, true /* automaticResizeOn */,
+          /* capabilities= */ new VideoEncoder.Capabilities(false /* lossNotification */));
   private static final int ENCODE_TIMEOUT_MS = 1000;
   private static final int NUM_TEST_FRAMES = 10;
   private static final int NUM_ENCODE_TRIES = 100;
diff --git a/sdk/android/src/jni/android_media_encoder.cc b/sdk/android/src/jni/android_media_encoder.cc
index 4bca01f..5a5f90b 100644
--- a/sdk/android/src/jni/android_media_encoder.cc
+++ b/sdk/android/src/jni/android_media_encoder.cc
@@ -97,8 +97,7 @@
 
   // VideoEncoder implementation.
   int32_t InitEncode(const VideoCodec* codec_settings,
-                     int32_t /* number_of_cores */,
-                     size_t /* max_payload_size */) override;
+                     const Settings& settings) override;
   int32_t Encode(const VideoFrame& input_image,
                  const std::vector<VideoFrameType>* frame_types) override;
   int32_t RegisterEncodeCompleteCallback(
@@ -304,8 +303,7 @@
 }
 
 int32_t MediaCodecVideoEncoder::InitEncode(const VideoCodec* codec_settings,
-                                           int32_t /* number_of_cores */,
-                                           size_t /* max_payload_size */) {
+                                           const Settings& settings) {
   RTC_DCHECK_RUN_ON(&encoder_queue_checker_);
   if (codec_settings == NULL) {
     ALOGE << "NULL VideoCodec instance";
diff --git a/sdk/android/src/jni/video_encoder_wrapper.cc b/sdk/android/src/jni/video_encoder_wrapper.cc
index aac4c27a..e051b77 100644
--- a/sdk/android/src/jni/video_encoder_wrapper.cc
+++ b/sdk/android/src/jni/video_encoder_wrapper.cc
@@ -38,13 +38,13 @@
 }
 VideoEncoderWrapper::~VideoEncoderWrapper() = default;
 
-int32_t VideoEncoderWrapper::InitEncode(const VideoCodec* codec_settings,
-                                        int32_t number_of_cores,
-                                        size_t max_payload_size) {
+int VideoEncoderWrapper::InitEncode(const VideoCodec* codec_settings,
+                                    const Settings& settings) {
   JNIEnv* jni = AttachCurrentThreadIfNeeded();
 
-  number_of_cores_ = number_of_cores;
   codec_settings_ = *codec_settings;
+  capabilities_ = settings.capabilities;
+  number_of_cores_ = settings.number_of_cores;
   num_resets_ = 0;
   {
     rtc::CritScope lock(&encoder_queue_crit_);
@@ -69,12 +69,16 @@
       automatic_resize_on = true;
   }
 
+  RTC_DCHECK(capabilities_);
+  ScopedJavaLocalRef<jobject> capabilities =
+      Java_Capabilities_Constructor(jni, capabilities_->loss_notification);
+
   ScopedJavaLocalRef<jobject> settings = Java_Settings_Constructor(
       jni, number_of_cores_, codec_settings_.width, codec_settings_.height,
       static_cast<int>(codec_settings_.startBitrate),
       static_cast<int>(codec_settings_.maxFramerate),
       static_cast<int>(codec_settings_.numberOfSimulcastStreams),
-      automatic_resize_on);
+      automatic_resize_on, capabilities);
 
   ScopedJavaLocalRef<jobject> callback =
       Java_VideoEncoderWrapper_createEncoderCallback(jni,
diff --git a/sdk/android/src/jni/video_encoder_wrapper.h b/sdk/android/src/jni/video_encoder_wrapper.h
index c140495..43d1f6f 100644
--- a/sdk/android/src/jni/video_encoder_wrapper.h
+++ b/sdk/android/src/jni/video_encoder_wrapper.h
@@ -16,6 +16,7 @@
 #include <string>
 #include <vector>
 
+#include "absl/types/optional.h"
 #include "api/task_queue/task_queue_base.h"
 #include "api/video_codecs/video_encoder.h"
 #include "common_video/h264/h264_bitstream_parser.h"
@@ -33,8 +34,7 @@
   ~VideoEncoderWrapper() override;
 
   int32_t InitEncode(const VideoCodec* codec_settings,
-                     int32_t number_of_cores,
-                     size_t max_payload_size) override;
+                     const Settings& settings) override;
 
   int32_t RegisterEncodeCompleteCallback(
       EncodedImageCallback* callback) override;
@@ -95,6 +95,7 @@
   EncodedImageCallback* callback_;
   bool initialized_;
   int num_resets_;
+  absl::optional<VideoEncoder::Capabilities> capabilities_;
   int number_of_cores_;
   VideoCodec codec_settings_;
   EncoderInfo encoder_info_;
diff --git a/sdk/android/tests/src/org/webrtc/HardwareVideoEncoderTest.java b/sdk/android/tests/src/org/webrtc/HardwareVideoEncoderTest.java
index 336988e..a08157d 100644
--- a/sdk/android/tests/src/org/webrtc/HardwareVideoEncoderTest.java
+++ b/sdk/android/tests/src/org/webrtc/HardwareVideoEncoderTest.java
@@ -58,7 +58,8 @@
       /* startBitrate= */ 10000,
       /* maxFramerate= */ 30,
       /* numberOfSimulcastStreams= */ 1,
-      /* automaticResizeOn= */ true);
+      /* automaticResizeOn= */ true,
+      /* capabilities= */ new VideoEncoder.Capabilities(false /* lossNotification */));
   private static final long POLL_DELAY_MS = 10;
   private static final long DELIVER_ENCODED_IMAGE_DELAY_MS = 10;
 
diff --git a/sdk/objc/native/src/objc_video_encoder_factory.mm b/sdk/objc/native/src/objc_video_encoder_factory.mm
index 7de9875..e59c1a1 100644
--- a/sdk/objc/native/src/objc_video_encoder_factory.mm
+++ b/sdk/objc/native/src/objc_video_encoder_factory.mm
@@ -41,12 +41,11 @@
   ObjCVideoEncoder(id<RTCVideoEncoder> encoder)
       : encoder_(encoder), implementation_name_([encoder implementationName].stdString) {}
 
-  int32_t InitEncode(const VideoCodec *codec_settings,
-                     int32_t number_of_cores,
-                     size_t max_payload_size) override {
+  int32_t InitEncode(const VideoCodec *codec_settings, const Settings &encoder_settings) override {
     RTCVideoEncoderSettings *settings =
         [[RTCVideoEncoderSettings alloc] initWithNativeVideoCodec:codec_settings];
-    return [encoder_ startEncodeWithSettings:settings numberOfCores:number_of_cores];
+    return [encoder_ startEncodeWithSettings:settings
+                               numberOfCores:encoder_settings.number_of_cores];
   }
 
   int32_t RegisterEncodeCompleteCallback(EncodedImageCallback *callback) override {
diff --git a/sdk/objc/unittests/objc_video_encoder_factory_tests.mm b/sdk/objc/unittests/objc_video_encoder_factory_tests.mm
index 567622c..70ef068 100644
--- a/sdk/objc/unittests/objc_video_encoder_factory_tests.mm
+++ b/sdk/objc/unittests/objc_video_encoder_factory_tests.mm
@@ -13,12 +13,12 @@
 
 #include "sdk/objc/native/src/objc_video_encoder_factory.h"
 
+#include "api/video_codecs/sdp_video_format.h"
+#include "api/video_codecs/video_encoder.h"
 #import "base/RTCVideoEncoder.h"
 #import "base/RTCVideoEncoderFactory.h"
 #import "base/RTCVideoFrameBuffer.h"
 #import "components/video_frame_buffer/RTCCVPixelBuffer.h"
-
-#include "api/video_codecs/sdp_video_format.h"
 #include "modules/include/module_common_types.h"
 #include "modules/video_coding/include/video_codec_interface.h"
 #include "modules/video_coding/include/video_error_codes.h"
@@ -61,14 +61,18 @@
   std::unique_ptr<webrtc::VideoEncoder> encoder = GetObjCEncoder(CreateOKEncoderFactory());
 
   auto* settings = new webrtc::VideoCodec();
-  EXPECT_EQ(encoder->InitEncode(settings, 1, 0), WEBRTC_VIDEO_CODEC_OK);
+  const webrtc::VideoEncoder::Capabilities kCapabilities(false);
+  EXPECT_EQ(encoder->InitEncode(settings, webrtc::VideoEncoder::Settings(kCapabilities, 1, 0)),
+            WEBRTC_VIDEO_CODEC_OK);
 }
 
 TEST(ObjCVideoEncoderFactoryTest, InitEncodeReturnsErrorOnFail) {
   std::unique_ptr<webrtc::VideoEncoder> encoder = GetObjCEncoder(CreateErrorEncoderFactory());
 
   auto* settings = new webrtc::VideoCodec();
-  EXPECT_EQ(encoder->InitEncode(settings, 1, 0), WEBRTC_VIDEO_CODEC_ERROR);
+  const webrtc::VideoEncoder::Capabilities kCapabilities(false);
+  EXPECT_EQ(encoder->InitEncode(settings, webrtc::VideoEncoder::Settings(kCapabilities, 1, 0)),
+            WEBRTC_VIDEO_CODEC_ERROR);
 }
 
 TEST(ObjCVideoEncoderFactoryTest, EncodeReturnsOKOnSuccess) {
diff --git a/test/configurable_frame_size_encoder.cc b/test/configurable_frame_size_encoder.cc
index ba529cb..7732607 100644
--- a/test/configurable_frame_size_encoder.cc
+++ b/test/configurable_frame_size_encoder.cc
@@ -38,8 +38,7 @@
 
 int32_t ConfigurableFrameSizeEncoder::InitEncode(
     const VideoCodec* codec_settings,
-    int32_t number_of_cores,
-    size_t max_payload_size) {
+    const Settings& settings) {
   return WEBRTC_VIDEO_CODEC_OK;
 }
 
diff --git a/test/configurable_frame_size_encoder.h b/test/configurable_frame_size_encoder.h
index ddf763f..679d3bd9 100644
--- a/test/configurable_frame_size_encoder.h
+++ b/test/configurable_frame_size_encoder.h
@@ -33,8 +33,7 @@
   ~ConfigurableFrameSizeEncoder() override;
 
   int32_t InitEncode(const VideoCodec* codec_settings,
-                     int32_t number_of_cores,
-                     size_t max_payload_size) override;
+                     const Settings& settings) override;
 
   int32_t Encode(const VideoFrame& input_image,
                  const std::vector<VideoFrameType>* frame_types) override;
diff --git a/test/fake_encoder.cc b/test/fake_encoder.cc
index fa7641c..23b6094 100644
--- a/test/fake_encoder.cc
+++ b/test/fake_encoder.cc
@@ -68,8 +68,7 @@
 }
 
 int32_t FakeEncoder::InitEncode(const VideoCodec* config,
-                                int32_t number_of_cores,
-                                size_t max_payload_size) {
+                                const Settings& settings) {
   rtc::CritScope cs(&crit_sect_);
   config_ = *config;
   current_rate_settings_.bitrate.SetBitrate(0, 0, config_.startBitrate * 1000);
@@ -364,8 +363,7 @@
 }
 
 int32_t MultithreadedFakeH264Encoder::InitEncode(const VideoCodec* config,
-                                                 int32_t number_of_cores,
-                                                 size_t max_payload_size) {
+                                                 const Settings& settings) {
   RTC_DCHECK_RUN_ON(&sequence_checker_);
 
   queue1_ = task_queue_factory_->CreateTaskQueue(
@@ -373,7 +371,7 @@
   queue2_ = task_queue_factory_->CreateTaskQueue(
       "Queue 2", TaskQueueFactory::Priority::NORMAL);
 
-  return FakeH264Encoder::InitEncode(config, number_of_cores, max_payload_size);
+  return FakeH264Encoder::InitEncode(config, settings);
 }
 
 class MultithreadedFakeH264Encoder::EncodeTask : public QueuedTask {
diff --git a/test/fake_encoder.h b/test/fake_encoder.h
index 7e1c1a1..f23ec1e 100644
--- a/test/fake_encoder.h
+++ b/test/fake_encoder.h
@@ -41,8 +41,7 @@
   void SetMaxBitrate(int max_kbps);
 
   int32_t InitEncode(const VideoCodec* config,
-                     int32_t number_of_cores,
-                     size_t max_payload_size) override;
+                     const Settings& settings) override;
   int32_t Encode(const VideoFrame& input_image,
                  const std::vector<VideoFrameType>* frame_types) override;
   int32_t RegisterEncodeCompleteCallback(
@@ -139,8 +138,7 @@
   virtual ~MultithreadedFakeH264Encoder() = default;
 
   int32_t InitEncode(const VideoCodec* config,
-                     int32_t number_of_cores,
-                     size_t max_payload_size) override;
+                     const Settings& settings) override;
 
   int32_t Encode(const VideoFrame& input_image,
                  const std::vector<VideoFrameType>* frame_types) override;
diff --git a/test/fake_vp8_encoder.cc b/test/fake_vp8_encoder.cc
index dd60a48..ee7a7ab 100644
--- a/test/fake_vp8_encoder.cc
+++ b/test/fake_vp8_encoder.cc
@@ -13,6 +13,7 @@
 #include <algorithm>
 
 #include "absl/types/optional.h"
+#include "api/video_codecs/video_encoder.h"
 #include "api/video_codecs/vp8_temporal_layers.h"
 #include "api/video_codecs/vp8_temporal_layers_factory.h"
 #include "modules/video_coding/codecs/interface/common_constants.h"
@@ -49,11 +50,9 @@
 }
 
 int32_t FakeVP8Encoder::InitEncode(const VideoCodec* config,
-                                   int32_t number_of_cores,
-                                   size_t max_payload_size) {
+                                   const Settings& settings) {
   RTC_DCHECK_RUN_ON(&sequence_checker_);
-  auto result =
-      FakeEncoder::InitEncode(config, number_of_cores, max_payload_size);
+  auto result = FakeEncoder::InitEncode(config, settings);
   if (result != WEBRTC_VIDEO_CODEC_OK) {
     return result;
   }
diff --git a/test/fake_vp8_encoder.h b/test/fake_vp8_encoder.h
index b5733c8..dcfa5ad 100644
--- a/test/fake_vp8_encoder.h
+++ b/test/fake_vp8_encoder.h
@@ -37,8 +37,7 @@
   virtual ~FakeVP8Encoder() = default;
 
   int32_t InitEncode(const VideoCodec* config,
-                     int32_t number_of_cores,
-                     size_t max_payload_size) override;
+                     const Settings& settings) override;
 
   int32_t Release() override;
 
diff --git a/test/pc/e2e/analyzer/video/quality_analyzing_video_encoder.cc b/test/pc/e2e/analyzer/video/quality_analyzing_video_encoder.cc
index 272f80f..3fa9a5b 100644
--- a/test/pc/e2e/analyzer/video/quality_analyzing_video_encoder.cc
+++ b/test/pc/e2e/analyzer/video/quality_analyzing_video_encoder.cc
@@ -15,6 +15,7 @@
 
 #include "absl/memory/memory.h"
 #include "api/video/video_codec_type.h"
+#include "api/video_codecs/video_encoder.h"
 #include "modules/video_coding/include/video_error_codes.h"
 #include "rtc_base/critical_section.h"
 #include "rtc_base/logging.h"
@@ -70,8 +71,7 @@
 
 int32_t QualityAnalyzingVideoEncoder::InitEncode(
     const VideoCodec* codec_settings,
-    int32_t number_of_cores,
-    size_t max_payload_size) {
+    const Settings& settings) {
   rtc::CritScope crit(&lock_);
   codec_settings_ = *codec_settings;
   mode_ = SimulcastMode::kNormal;
@@ -96,8 +96,7 @@
   if (codec_settings->numberOfSimulcastStreams > 1) {
     mode_ = SimulcastMode::kSimulcast;
   }
-  return delegate_->InitEncode(codec_settings, number_of_cores,
-                               max_payload_size);
+  return delegate_->InitEncode(codec_settings, settings);
 }
 
 int32_t QualityAnalyzingVideoEncoder::RegisterEncodeCompleteCallback(
diff --git a/test/pc/e2e/analyzer/video/quality_analyzing_video_encoder.h b/test/pc/e2e/analyzer/video/quality_analyzing_video_encoder.h
index 4861d4c..6b22ae2 100644
--- a/test/pc/e2e/analyzer/video/quality_analyzing_video_encoder.h
+++ b/test/pc/e2e/analyzer/video/quality_analyzing_video_encoder.h
@@ -63,8 +63,7 @@
 
   // Methods of VideoEncoder interface.
   int32_t InitEncode(const VideoCodec* codec_settings,
-                     int32_t number_of_cores,
-                     size_t max_payload_size) override;
+                     const Settings& settings) override;
   int32_t RegisterEncodeCompleteCallback(
       EncodedImageCallback* callback) override;
   int32_t Release() override;
diff --git a/test/video_encoder_proxy_factory.h b/test/video_encoder_proxy_factory.h
index 49a4e2d..81183d3 100644
--- a/test/video_encoder_proxy_factory.h
+++ b/test/video_encoder_proxy_factory.h
@@ -21,6 +21,10 @@
 namespace webrtc {
 namespace test {
 
+namespace {
+const VideoEncoder::Capabilities kCapabilities(false);
+}
+
 // An encoder factory with a single underlying VideoEncoder object,
 // intended for test purposes. Each call to CreateVideoEncoder returns
 // a proxy for the same encoder, typically an instance of FakeEncoder.
@@ -66,9 +70,8 @@
       return encoder_->Encode(input_image, frame_types);
     }
     int32_t InitEncode(const VideoCodec* config,
-                       int32_t number_of_cores,
-                       size_t max_payload_size) override {
-      return encoder_->InitEncode(config, number_of_cores, max_payload_size);
+                       const Settings& settings) override {
+      return encoder_->InitEncode(config, settings);
     }
     int32_t RegisterEncodeCompleteCallback(
         EncodedImageCallback* callback) override {
diff --git a/video/BUILD.gn b/video/BUILD.gn
index 0ae719a..ea09c16 100644
--- a/video/BUILD.gn
+++ b/video/BUILD.gn
@@ -262,6 +262,7 @@
       "../api/video:video_bitrate_allocator_factory",
       "../api/video:video_frame",
       "../api/video:video_rtp_headers",
+      "../api/video_codecs:video_codecs_api",
       "../call:fake_network",
       "../call:simulated_network",
       "../common_video",
diff --git a/video/end_to_end_tests/network_state_tests.cc b/video/end_to_end_tests/network_state_tests.cc
index a863076..218414e 100644
--- a/video/end_to_end_tests/network_state_tests.cc
+++ b/video/end_to_end_tests/network_state_tests.cc
@@ -10,6 +10,7 @@
 
 #include "absl/memory/memory.h"
 #include "api/test/simulated_network.h"
+#include "api/video_codecs/video_encoder.h"
 #include "call/fake_network_pipe.h"
 #include "call/simulated_network.h"
 #include "system_wrappers/include/sleep.h"
@@ -356,8 +357,7 @@
     UnusedEncoder() : FakeEncoder(Clock::GetRealTimeClock()) {}
 
     int32_t InitEncode(const VideoCodec* config,
-                       int32_t number_of_cores,
-                       size_t max_payload_size) override {
+                       const Settings& settings) override {
       EXPECT_GT(config->startBitrate, 0u);
       return 0;
     }
diff --git a/video/video_quality_test.cc b/video/video_quality_test.cc
index cc30c79..4a45357 100644
--- a/video/video_quality_test.cc
+++ b/video/video_quality_test.cc
@@ -21,6 +21,7 @@
 #include "api/rtc_event_log_output_file.h"
 #include "api/task_queue/default_task_queue_factory.h"
 #include "api/video/builtin_video_bitrate_allocator_factory.h"
+#include "api/video_codecs/video_encoder.h"
 #include "call/fake_network_pipe.h"
 #include "call/simulated_network.h"
 #include "media/engine/adm_helpers.h"
@@ -67,6 +68,8 @@
 
 constexpr int kDefaultMaxQp = cricket::WebRtcVideoChannel::kDefaultQpMax;
 
+const VideoEncoder::Capabilities kCapabilities(false);
+
 std::pair<uint32_t, uint32_t> GetMinMaxBitratesBps(const VideoCodec& codec,
                                                    size_t spatial_idx) {
   uint32_t min_bitrate = codec.minBitrate;
@@ -132,11 +135,9 @@
 
   // Implement VideoEncoder
   int32_t InitEncode(const VideoCodec* codec_settings,
-                     int32_t number_of_cores,
-                     size_t max_payload_size) override {
+                     const Settings& settings) override {
     codec_settings_ = *codec_settings;
-    return encoder_->InitEncode(codec_settings, number_of_cores,
-                                max_payload_size);
+    return encoder_->InitEncode(codec_settings, settings);
   }
 
   int32_t RegisterEncodeCompleteCallback(
diff --git a/video/video_send_stream_tests.cc b/video/video_send_stream_tests.cc
index 480ae6c..fc5a5b9 100644
--- a/video/video_send_stream_tests.cc
+++ b/video/video_send_stream_tests.cc
@@ -17,6 +17,7 @@
 #include "api/test/simulated_network.h"
 #include "api/video/encoded_image.h"
 #include "api/video/video_bitrate_allocation.h"
+#include "api/video_codecs/video_encoder.h"
 #include "call/call.h"
 #include "call/fake_network_pipe.h"
 #include "call/rtp_transport_controller_send.h"
@@ -1976,14 +1977,13 @@
 
    private:
     int32_t InitEncode(const VideoCodec* config,
-                       int32_t number_of_cores,
-                       size_t max_payload_size) override {
+                       const Settings& settings) override {
       rtc::CritScope lock(&crit_);
       last_initialized_frame_width_ = config->width;
       last_initialized_frame_height_ = config->height;
       ++number_of_initializations_;
       init_encode_called_.Set();
-      return FakeEncoder::InitEncode(config, number_of_cores, max_payload_size);
+      return FakeEncoder::InitEncode(config, settings);
     }
 
     int32_t Encode(const VideoFrame& input_image,
@@ -2036,12 +2036,11 @@
         : FakeEncoder(Clock::GetRealTimeClock()),
           start_bitrate_kbps_(0) {}
     int32_t InitEncode(const VideoCodec* config,
-                       int32_t number_of_cores,
-                       size_t max_payload_size) override {
+                       const Settings& settings) override {
       rtc::CritScope lock(&crit_);
       start_bitrate_kbps_ = config->startBitrate;
       start_bitrate_changed_.Set();
-      return FakeEncoder::InitEncode(config, number_of_cores, max_payload_size);
+      return FakeEncoder::InitEncode(config, settings);
     }
 
     void SetRates(const RateControlParameters& parameters) override {
@@ -2110,11 +2109,10 @@
  public:
   StartStopBitrateObserver() : FakeEncoder(Clock::GetRealTimeClock()) {}
   int32_t InitEncode(const VideoCodec* config,
-                     int32_t number_of_cores,
-                     size_t max_payload_size) override {
+                     const Settings& settings) override {
     rtc::CritScope lock(&crit_);
     encoder_init_.Set();
-    return FakeEncoder::InitEncode(config, number_of_cores, max_payload_size);
+    return FakeEncoder::InitEncode(config, settings);
   }
 
   void SetRates(const RateControlParameters& parameters) override {
@@ -2309,8 +2307,7 @@
 
    private:
     int32_t InitEncode(const VideoCodec* codecSettings,
-                       int32_t numberOfCores,
-                       size_t maxPayloadSize) override {
+                       const Settings& settings) override {
       rtc::CritScope lock(&crit_);
       EXPECT_FALSE(initialized_);
       initialized_ = true;
@@ -2426,8 +2423,7 @@
     }
 
     int32_t InitEncode(const VideoCodec* config,
-                       int32_t number_of_cores,
-                       size_t max_payload_size) override {
+                       const Settings& settings) override {
       if (num_initializations_ == 0) {
         // Verify default values.
         EXPECT_EQ(kFirstMaxBitrateBps / 1000, config->maxBitrate);
@@ -2437,7 +2433,7 @@
       }
       ++num_initializations_;
       init_encode_event_.Set();
-      return FakeEncoder::InitEncode(config, number_of_cores, max_payload_size);
+      return FakeEncoder::InitEncode(config, settings);
     }
 
     void PerformTest() override {
@@ -2505,13 +2501,12 @@
   }
 
   int32_t InitEncode(const VideoCodec* config,
-                     int32_t number_of_cores,
-                     size_t max_payload_size) override {
+                     const Settings& settings) override {
     EXPECT_EQ(video_codec_type_, config->codecType);
     VerifyCodecSpecifics(*config);
     ++num_initializations_;
     init_encode_event_.Set();
-    return FakeEncoder::InitEncode(config, number_of_cores, max_payload_size);
+    return FakeEncoder::InitEncode(config, settings);
   }
 
   void InitCodecSpecifics();
@@ -2753,16 +2748,15 @@
 
    private:
     int32_t InitEncode(const VideoCodec* config,
-                       int32_t number_of_cores,
-                       size_t max_payload_size) override {
+                       const Settings& settings) override {
       EXPECT_EQ(config->numberOfSimulcastStreams, 1);
       EXPECT_EQ(static_cast<unsigned int>(kScreencastMaxTargetBitrateDeltaKbps),
                 config->simulcastStream[0].maxBitrate -
                     config->simulcastStream[0].targetBitrate);
       observation_complete_.Set();
-      return test::FakeEncoder::InitEncode(config, number_of_cores,
-                                           max_payload_size);
+      return test::FakeEncoder::InitEncode(config, settings);
     }
+
     void ModifyVideoConfigs(
         VideoSendStream::Config* send_config,
         std::vector<VideoReceiveStream::Config>* receive_configs,
@@ -2818,8 +2812,7 @@
 
    private:
     int32_t InitEncode(const VideoCodec* codecSettings,
-                       int32_t numberOfCores,
-                       size_t maxPayloadSize) override {
+                       const Settings& settings) override {
       EXPECT_GE(codecSettings->startBitrate, codecSettings->minBitrate);
       EXPECT_LE(codecSettings->startBitrate, codecSettings->maxBitrate);
       if (num_initializations_ == 0) {
@@ -2847,8 +2840,7 @@
       ++num_initializations_;
       init_encode_event_.Set();
 
-      return FakeEncoder::InitEncode(codecSettings, numberOfCores,
-                                     maxPayloadSize);
+      return FakeEncoder::InitEncode(codecSettings, settings);
     }
 
     void SetRates(const RateControlParameters& parameters) override {
diff --git a/video/video_stream_encoder.cc b/video/video_stream_encoder.cc
index fab3d57..56835d6 100644
--- a/video/video_stream_encoder.cc
+++ b/video/video_stream_encoder.cc
@@ -20,6 +20,7 @@
 #include "api/video/encoded_image.h"
 #include "api/video/i420_buffer.h"
 #include "api/video/video_bitrate_allocator_factory.h"
+#include "api/video_codecs/video_encoder.h"
 #include "modules/video_coding/codecs/vp9/svc_rate_allocator.h"
 #include "modules/video_coding/include/video_codec_initializer.h"
 #include "modules/video_coding/include/video_coding.h"
@@ -732,10 +733,13 @@
           encoder_config_.video_format);
     }
 
-    if (encoder_->InitEncode(&send_codec_, number_of_cores_,
-                             max_data_payload_length_ > 0
-                                 ? max_data_payload_length_
-                                 : kDefaultPayloadSize) != 0) {
+    const size_t max_data_payload_length = max_data_payload_length_ > 0
+                                               ? max_data_payload_length_
+                                               : kDefaultPayloadSize;
+    if (encoder_->InitEncode(
+            &send_codec_,
+            VideoEncoder::Settings(settings_.capabilities, number_of_cores_,
+                                   max_data_payload_length)) != 0) {
       RTC_LOG(LS_ERROR) << "Failed to initialize the encoder associated with "
                            "codec type: "
                         << CodecTypeToPayloadString(send_codec_.codecType)
diff --git a/video/video_stream_encoder_unittest.cc b/video/video_stream_encoder_unittest.cc
index 1cf9436..1486606d 100644
--- a/video/video_stream_encoder_unittest.cc
+++ b/video/video_stream_encoder_unittest.cc
@@ -20,6 +20,7 @@
 #include "api/video/builtin_video_bitrate_allocator_factory.h"
 #include "api/video/i420_buffer.h"
 #include "api/video/video_bitrate_allocation.h"
+#include "api/video_codecs/video_encoder.h"
 #include "api/video_codecs/vp8_temporal_layers.h"
 #include "api/video_codecs/vp8_temporal_layers_factory.h"
 #include "common_video/h264/h264_common.h"
@@ -717,10 +718,8 @@
     }
 
     int32_t InitEncode(const VideoCodec* config,
-                       int32_t number_of_cores,
-                       size_t max_payload_size) override {
-      int res =
-          FakeEncoder::InitEncode(config, number_of_cores, max_payload_size);
+                       const Settings& settings) override {
+      int res = FakeEncoder::InitEncode(config, settings);
       rtc::CritScope lock(&local_crit_sect_);
       EXPECT_EQ(initialized_, EncoderState::kUninitialized);
       if (config->codecType == kVideoCodecVP8) {