Wire up BitrateAllocation to be sent as RTCP TargetBitrate

This is the video parts of https://codereview.webrtc.org/2531383002/
Wire up BitrateAllocation to be sent as RTCP TargetBitrate

BUG=webrtc:6301

Review-Url: https://codereview.webrtc.org/2541303003
Cr-Commit-Position: refs/heads/master@{#15359}
diff --git a/webrtc/common_video/include/video_bitrate_allocator.h b/webrtc/common_video/include/video_bitrate_allocator.h
index 66ff077..b85879d 100644
--- a/webrtc/common_video/include/video_bitrate_allocator.h
+++ b/webrtc/common_video/include/video_bitrate_allocator.h
@@ -25,6 +25,15 @@
   virtual uint32_t GetPreferredBitrateBps(uint32_t framerate) = 0;
 };
 
+class VideoBitrateAllocationObserver {
+ public:
+  VideoBitrateAllocationObserver() {}
+  virtual ~VideoBitrateAllocationObserver() {}
+
+  virtual void OnBitrateAllocationUpdated(
+      const BitrateAllocation& allocation) = 0;
+};
+
 }  // namespace webrtc
 
 #endif  // WEBRTC_COMMON_VIDEO_INCLUDE_VIDEO_BITRATE_ALLOCATOR_H_
diff --git a/webrtc/modules/video_coding/video_coding_impl.cc b/webrtc/modules/video_coding/video_coding_impl.cc
index 021281b..85511bc 100644
--- a/webrtc/modules/video_coding/video_coding_impl.cc
+++ b/webrtc/modules/video_coding/video_coding_impl.cc
@@ -146,7 +146,7 @@
                                uint8_t lossRate,
                                int64_t rtt) override {
     return sender_.SetChannelParameters(target_bitrate, lossRate, rtt,
-                                        rate_allocator_.get());
+                                        rate_allocator_.get(), nullptr);
   }
 
   int32_t RegisterProtectionCallback(
diff --git a/webrtc/modules/video_coding/video_coding_impl.h b/webrtc/modules/video_coding/video_coding_impl.h
index f6e5306..b5d04c4 100644
--- a/webrtc/modules/video_coding/video_coding_impl.h
+++ b/webrtc/modules/video_coding/video_coding_impl.h
@@ -35,6 +35,7 @@
 namespace webrtc {
 
 class VideoBitrateAllocator;
+class VideoBitrateAllocationObserver;
 
 namespace vcm {
 
@@ -79,14 +80,23 @@
   int Bitrate(unsigned int* bitrate) const;
   int FrameRate(unsigned int* framerate) const;
 
-  int32_t SetChannelParameters(uint32_t target_bitrate_bps,
-                               uint8_t lossRate,
-                               int64_t rtt,
-                               VideoBitrateAllocator* bitrate_allocator);
-  // Updates the channel parameters, with a reallocated bitrate based on a
-  // presumably updated codec configuration, but does not update the encoder
-  // itself (it will be updated on the next frame).
-  void UpdateChannelParemeters(VideoBitrateAllocator* bitrate_allocator);
+  // Update the channel parameters based on new rates and rtt. This will also
+  // cause an immediate call to VideoEncoder::SetRateAllocation().
+  int32_t SetChannelParameters(
+      uint32_t target_bitrate_bps,
+      uint8_t loss_rate,
+      int64_t rtt,
+      VideoBitrateAllocator* bitrate_allocator,
+      VideoBitrateAllocationObserver* bitrate_updated_callback);
+
+  // Updates the channel parameters with a new bitrate allocation, but using the
+  // current targit_bitrate, loss rate and rtt. That is, the distribution or
+  // caps may be updated to a change to a new VideoCodec or allocation mode.
+  // The new parameters will be stored as pending EncoderParameters, and the
+  // encoder will only be updated on the next frame.
+  void UpdateChannelParemeters(
+      VideoBitrateAllocator* bitrate_allocator,
+      VideoBitrateAllocationObserver* bitrate_updated_callback);
 
   // Deprecated:
   // TODO(perkj): Remove once no projects use it.
diff --git a/webrtc/modules/video_coding/video_sender.cc b/webrtc/modules/video_coding/video_sender.cc
index d754c56..536e33a 100644
--- a/webrtc/modules/video_coding/video_sender.cc
+++ b/webrtc/modules/video_coding/video_sender.cc
@@ -63,7 +63,6 @@
       send_stats_callback_->SendStatistics(bitRate, frameRate);
     }
   }
-
   {
     rtc::CritScope cs(&params_crit_);
     // Force an encoder parameters update, so that incoming frame rate is
@@ -122,6 +121,7 @@
   } else if (frame_dropper_enabled_) {
     _mediaOpt.EnableFrameDropper(true);
   }
+
   {
     rtc::CritScope cs(&params_crit_);
     next_frame_types_.clear();
@@ -212,30 +212,41 @@
     bitrate_allocation = default_allocator.GetAllocation(video_target_rate_bps,
                                                          input_frame_rate);
   }
-
   EncoderParameters new_encoder_params = {bitrate_allocation, params.loss_rate,
                                           params.rtt, input_frame_rate};
   return new_encoder_params;
 }
 
 void VideoSender::UpdateChannelParemeters(
-    VideoBitrateAllocator* bitrate_allocator) {
-  rtc::CritScope cs(&params_crit_);
-  encoder_params_ =
-      UpdateEncoderParameters(encoder_params_, bitrate_allocator,
-                              encoder_params_.target_bitrate.get_sum_bps());
+    VideoBitrateAllocator* bitrate_allocator,
+    VideoBitrateAllocationObserver* bitrate_updated_callback) {
+  BitrateAllocation target_rate;
+  {
+    rtc::CritScope cs(&params_crit_);
+    encoder_params_ =
+        UpdateEncoderParameters(encoder_params_, bitrate_allocator,
+                                encoder_params_.target_bitrate.get_sum_bps());
+    target_rate = encoder_params_.target_bitrate;
+  }
+  if (bitrate_updated_callback)
+    bitrate_updated_callback->OnBitrateAllocationUpdated(target_rate);
 }
 
 int32_t VideoSender::SetChannelParameters(
     uint32_t target_bitrate_bps,
-    uint8_t lossRate,
+    uint8_t loss_rate,
     int64_t rtt,
-    VideoBitrateAllocator* bitrate_allocator) {
+    VideoBitrateAllocator* bitrate_allocator,
+    VideoBitrateAllocationObserver* bitrate_updated_callback) {
   EncoderParameters encoder_params;
-  encoder_params.loss_rate = lossRate;
+  encoder_params.loss_rate = loss_rate;
   encoder_params.rtt = rtt;
   encoder_params = UpdateEncoderParameters(encoder_params, bitrate_allocator,
                                            target_bitrate_bps);
+  if (bitrate_updated_callback) {
+    bitrate_updated_callback->OnBitrateAllocationUpdated(
+        encoder_params.target_bitrate);
+  }
 
   bool encoder_has_internal_source;
   {
diff --git a/webrtc/modules/video_coding/video_sender_unittest.cc b/webrtc/modules/video_coding/video_sender_unittest.cc
index e24bbd7..a670d8f 100644
--- a/webrtc/modules/video_coding/video_sender_unittest.cc
+++ b/webrtc/modules/video_coding/video_sender_unittest.cc
@@ -312,7 +312,7 @@
       .Times(1)
       .WillOnce(Return(0));
   sender_->SetChannelParameters(new_bitrate_kbps * 1000, 0, 200,
-                                rate_allocator_.get());
+                                rate_allocator_.get(), nullptr);
   AddFrame();
   clock_.AdvanceTimeMilliseconds(kFrameIntervalMs);
 
@@ -334,7 +334,7 @@
 
   // Expect no call to encoder_.SetRates if the new bitrate is zero.
   EXPECT_CALL(encoder_, SetRateAllocation(_, _)).Times(0);
-  sender_->SetChannelParameters(0, 0, 200, rate_allocator_.get());
+  sender_->SetChannelParameters(0, 0, 200, rate_allocator_.get(), nullptr);
   AddFrame();
 }
 
@@ -372,12 +372,12 @@
       .Times(1)
       .WillOnce(Return(0));
   sender_->SetChannelParameters(new_bitrate_kbps * 1000, 0, 200,
-                                rate_allocator_.get());
+                                rate_allocator_.get(), nullptr);
 }
 
 TEST_F(TestVideoSenderWithMockEncoder, EncoderFramerateUpdatedViaProcess) {
   sender_->SetChannelParameters(settings_.startBitrate * 1000, 0, 200,
-                                rate_allocator_.get());
+                                rate_allocator_.get(), nullptr);
   const int64_t kRateStatsWindowMs = 2000;
   const uint32_t kInputFps = 20;
   int64_t start_time = clock_.TimeInMilliseconds();
@@ -406,7 +406,7 @@
       .Times(1)
       .WillOnce(Return(0));
   sender_->SetChannelParameters(settings_.startBitrate * 1000, kLossRate, kRtt,
-                                rate_allocator_.get());
+                                rate_allocator_.get(), nullptr);
   while (clock_.TimeInMilliseconds() < start_time + kRateStatsWindowMs) {
     AddFrame();
     clock_.AdvanceTimeMilliseconds(1000 / kInputFps);
@@ -427,7 +427,7 @@
       .Times(1)
       .WillOnce(Return(0));
   sender_->SetChannelParameters(new_bitrate_bps, kLossRate, kRtt,
-                                rate_allocator_.get());
+                                rate_allocator_.get(), nullptr);
   AddFrame();
 }
 
@@ -481,9 +481,9 @@
       // Note: SetChannelParameters fails if less than 2 frames are in the
       // buffer since it will fail to calculate the framerate.
       if (i != 0) {
-        EXPECT_EQ(VCM_OK,
-                  sender_->SetChannelParameters(available_bitrate_kbps_ * 1000,
-                                                0, 200, rate_allocator_.get()));
+        EXPECT_EQ(VCM_OK, sender_->SetChannelParameters(
+                              available_bitrate_kbps_ * 1000, 0, 200,
+                              rate_allocator_.get(), nullptr));
       }
     }
   }
diff --git a/webrtc/video/end_to_end_tests.cc b/webrtc/video/end_to_end_tests.cc
index 86c181b..4de6db4 100644
--- a/webrtc/video/end_to_end_tests.cc
+++ b/webrtc/video/end_to_end_tests.cc
@@ -125,7 +125,6 @@
   void DecodesRetransmittedFrame(bool enable_rtx, bool enable_red);
   void ReceivesPliAndRecovers(int rtp_history_ms);
   void RespectsRtcpMode(RtcpMode rtcp_mode);
-  void TestXrReceiverReferenceTimeReport(bool enable_rrtr);
   void TestSendsSetSsrcs(size_t num_ssrcs, bool send_single_ssrc_first);
   void TestRtpStatePreservation(bool use_rtx, bool provoke_rtcpsr_before_rtp);
   void VerifyHistogramStats(bool use_rtx, bool use_red, bool screenshare);
@@ -2435,89 +2434,6 @@
   VerifyHistogramStats(kEnabledRtx, kEnabledRed, kScreenshare);
 }
 
-void EndToEndTest::TestXrReceiverReferenceTimeReport(bool enable_rrtr) {
-  static const int kNumRtcpReportPacketsToObserve = 5;
-  class RtcpXrObserver : public test::EndToEndTest {
-   public:
-    explicit RtcpXrObserver(bool enable_rrtr)
-        : EndToEndTest(kDefaultTimeoutMs),
-          enable_rrtr_(enable_rrtr),
-          sent_rtcp_sr_(0),
-          sent_rtcp_rr_(0),
-          sent_rtcp_rrtr_(0),
-          sent_rtcp_dlrr_(0) {}
-
-   private:
-    // Receive stream should send RR packets (and RRTR packets if enabled).
-    Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
-      rtc::CritScope lock(&crit_);
-      test::RtcpPacketParser parser;
-      EXPECT_TRUE(parser.Parse(packet, length));
-
-      sent_rtcp_rr_ += parser.receiver_report()->num_packets();
-      EXPECT_EQ(0, parser.sender_report()->num_packets());
-      EXPECT_GE(1, parser.xr()->num_packets());
-      if (parser.xr()->num_packets() > 0) {
-        if (parser.xr()->rrtr())
-          ++sent_rtcp_rrtr_;
-        EXPECT_FALSE(parser.xr()->dlrr());
-      }
-
-      return SEND_PACKET;
-    }
-    // Send stream should send SR packets (and DLRR packets if enabled).
-    Action OnSendRtcp(const uint8_t* packet, size_t length) override {
-      rtc::CritScope lock(&crit_);
-      test::RtcpPacketParser parser;
-      EXPECT_TRUE(parser.Parse(packet, length));
-
-      sent_rtcp_sr_ += parser.sender_report()->num_packets();
-      EXPECT_GE(1, parser.xr()->num_packets());
-      if (parser.xr()->num_packets() > 0) {
-        EXPECT_FALSE(parser.xr()->rrtr());
-        if (parser.xr()->dlrr())
-          ++sent_rtcp_dlrr_;
-      }
-
-      if (sent_rtcp_sr_ > kNumRtcpReportPacketsToObserve &&
-          sent_rtcp_rr_ > kNumRtcpReportPacketsToObserve) {
-        if (enable_rrtr_) {
-          EXPECT_LT(0, sent_rtcp_rrtr_);
-          EXPECT_LT(0, sent_rtcp_dlrr_);
-        } else {
-          EXPECT_EQ(0, sent_rtcp_rrtr_);
-          EXPECT_EQ(0, sent_rtcp_dlrr_);
-        }
-        observation_complete_.Set();
-      }
-      return SEND_PACKET;
-    }
-
-    void ModifyVideoConfigs(
-        VideoSendStream::Config* send_config,
-        std::vector<VideoReceiveStream::Config>* receive_configs,
-        VideoEncoderConfig* encoder_config) override {
-      (*receive_configs)[0].rtp.rtcp_mode = RtcpMode::kReducedSize;
-      (*receive_configs)[0].rtp.rtcp_xr.receiver_reference_time_report =
-          enable_rrtr_;
-    }
-
-    void PerformTest() override {
-      EXPECT_TRUE(Wait())
-          << "Timed out while waiting for RTCP SR/RR packets to be sent.";
-    }
-
-    rtc::CriticalSection crit_;
-    bool enable_rrtr_;
-    int sent_rtcp_sr_;
-    int sent_rtcp_rr_ GUARDED_BY(&crit_);
-    int sent_rtcp_rrtr_ GUARDED_BY(&crit_);
-    int sent_rtcp_dlrr_;
-  } test(enable_rrtr);
-
-  RunBaseTest(&test);
-}
-
 void EndToEndTest::TestSendsSetSsrcs(size_t num_ssrcs,
                                      bool send_single_ssrc_first) {
   class SendsSetSsrcs : public test::EndToEndTest {
@@ -3064,12 +2980,99 @@
   RunBaseTest(&test);
 }
 
-TEST_P(EndToEndTest, ReceiverReferenceTimeReportEnabled) {
-  TestXrReceiverReferenceTimeReport(true);
+class RtcpXrObserver : public test::EndToEndTest {
+ public:
+  explicit RtcpXrObserver(bool enable_rrtr)
+      : EndToEndTest(test::CallTest::kDefaultTimeoutMs),
+        enable_rrtr_(enable_rrtr),
+        sent_rtcp_sr_(0),
+        sent_rtcp_rr_(0),
+        sent_rtcp_rrtr_(0),
+        sent_rtcp_target_bitrate_(false),
+        sent_rtcp_dlrr_(0) {}
+
+ private:
+  // Receive stream should send RR packets (and RRTR packets if enabled).
+  Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
+    rtc::CritScope lock(&crit_);
+    test::RtcpPacketParser parser;
+    EXPECT_TRUE(parser.Parse(packet, length));
+
+    sent_rtcp_rr_ += parser.receiver_report()->num_packets();
+    EXPECT_EQ(0, parser.sender_report()->num_packets());
+    EXPECT_GE(1, parser.xr()->num_packets());
+    if (parser.xr()->num_packets() > 0) {
+      if (parser.xr()->rrtr())
+        ++sent_rtcp_rrtr_;
+      EXPECT_FALSE(parser.xr()->dlrr());
+    }
+
+    return SEND_PACKET;
+  }
+  // Send stream should send SR packets (and DLRR packets if enabled).
+  Action OnSendRtcp(const uint8_t* packet, size_t length) override {
+    rtc::CritScope lock(&crit_);
+    test::RtcpPacketParser parser;
+    EXPECT_TRUE(parser.Parse(packet, length));
+
+    sent_rtcp_sr_ += parser.sender_report()->num_packets();
+    EXPECT_LE(parser.xr()->num_packets(), 1);
+    if (parser.xr()->num_packets() > 0) {
+      EXPECT_FALSE(parser.xr()->rrtr());
+      if (parser.xr()->dlrr())
+        ++sent_rtcp_dlrr_;
+      if (parser.xr()->target_bitrate())
+        sent_rtcp_target_bitrate_ = true;
+    }
+
+    if (sent_rtcp_sr_ > kNumRtcpReportPacketsToObserve &&
+        sent_rtcp_rr_ > kNumRtcpReportPacketsToObserve &&
+        sent_rtcp_target_bitrate_) {
+      if (enable_rrtr_) {
+        EXPECT_GT(sent_rtcp_rrtr_, 0);
+        EXPECT_GT(sent_rtcp_dlrr_, 0);
+      } else {
+        EXPECT_EQ(sent_rtcp_rrtr_, 0);
+        EXPECT_EQ(sent_rtcp_dlrr_, 0);
+      }
+      observation_complete_.Set();
+    }
+    return SEND_PACKET;
+  }
+
+  void ModifyVideoConfigs(
+      VideoSendStream::Config* send_config,
+      std::vector<VideoReceiveStream::Config>* receive_configs,
+      VideoEncoderConfig* encoder_config) override {
+    (*receive_configs)[0].rtp.rtcp_mode = RtcpMode::kReducedSize;
+    (*receive_configs)[0].rtp.rtcp_xr.receiver_reference_time_report =
+        enable_rrtr_;
+  }
+
+  void PerformTest() override {
+    EXPECT_TRUE(Wait())
+        << "Timed out while waiting for RTCP SR/RR packets to be sent.";
+  }
+
+  static const int kNumRtcpReportPacketsToObserve = 5;
+
+  rtc::CriticalSection crit_;
+  bool enable_rrtr_;
+  int sent_rtcp_sr_;
+  int sent_rtcp_rr_ GUARDED_BY(&crit_);
+  int sent_rtcp_rrtr_ GUARDED_BY(&crit_);
+  bool sent_rtcp_target_bitrate_ GUARDED_BY(&crit_);
+  int sent_rtcp_dlrr_;
+};
+
+TEST_P(EndToEndTest, TestExtendedReportsWithRrtr) {
+  RtcpXrObserver test(true);
+  RunBaseTest(&test);
 }
 
-TEST_P(EndToEndTest, ReceiverReferenceTimeReportDisabled) {
-  TestXrReceiverReferenceTimeReport(false);
+TEST_P(EndToEndTest, TestExtendedReportsWithoutRrtr) {
+  RtcpXrObserver test(false);
+  RunBaseTest(&test);
 }
 
 TEST_P(EndToEndTest, TestReceivedRtpPacketStats) {
diff --git a/webrtc/video/payload_router.cc b/webrtc/video/payload_router.cc
index 33d8f76..6c8e36f 100644
--- a/webrtc/video/payload_router.cc
+++ b/webrtc/video/payload_router.cc
@@ -101,7 +101,7 @@
   return IP_PACKET_SIZE - kIpUdpSrtpLength;
 }
 
-void PayloadRouter::set_active(bool active) {
+void PayloadRouter::SetActive(bool active) {
   rtc::CritScope lock(&crit_);
   if (active_ == active)
     return;
@@ -113,7 +113,7 @@
   }
 }
 
-bool PayloadRouter::active() {
+bool PayloadRouter::IsActive() {
   rtc::CritScope lock(&crit_);
   return active_ && !rtp_modules_.empty();
 }
@@ -158,4 +158,24 @@
   return min_payload_length;
 }
 
+void PayloadRouter::OnBitrateAllocationUpdated(
+    const BitrateAllocation& bitrate) {
+  rtc::CritScope lock(&crit_);
+  if (IsActive()) {
+    if (rtp_modules_.size() == 1) {
+      // If spatial scalability is enabled, it is covered by a single stream.
+      rtp_modules_[0]->SetVideoBitrateAllocation(bitrate);
+    } else {
+      // Simulcast is in use, split the BitrateAllocation into one struct per
+      // rtp stream, moving over the temporal layer allocation.
+      for (size_t si = 0; si < rtp_modules_.size(); ++si) {
+        BitrateAllocation layer_bitrate;
+        for (int tl = 0; tl < kMaxTemporalStreams; ++tl)
+          layer_bitrate.SetBitrate(0, tl, bitrate.GetBitrate(si, tl));
+        rtp_modules_[si]->SetVideoBitrateAllocation(layer_bitrate);
+      }
+    }
+  }
+}
+
 }  // namespace webrtc
diff --git a/webrtc/video/payload_router.h b/webrtc/video/payload_router.h
index 6426b00..3b60ce2 100644
--- a/webrtc/video/payload_router.h
+++ b/webrtc/video/payload_router.h
@@ -40,8 +40,8 @@
 
   // PayloadRouter will only route packets if being active, all packets will be
   // dropped otherwise.
-  void set_active(bool active);
-  bool active();
+  void SetActive(bool active);
+  bool IsActive();
 
   // Implements EncodedImageCallback.
   // Returns 0 if the packet was routed / sent, -1 otherwise.
@@ -54,6 +54,8 @@
   // and RTP headers.
   size_t MaxPayloadLength() const;
 
+  void OnBitrateAllocationUpdated(const BitrateAllocation& bitrate);
+
  private:
   void UpdateModuleSendingState() EXCLUSIVE_LOCKS_REQUIRED(crit_);
 
diff --git a/webrtc/video/payload_router_unittest.cc b/webrtc/video/payload_router_unittest.cc
index adddefe..935de5f 100644
--- a/webrtc/video/payload_router_unittest.cc
+++ b/webrtc/video/payload_router_unittest.cc
@@ -49,7 +49,7 @@
       EncodedImageCallback::Result::OK,
       payload_router.OnEncodedImage(encoded_image, nullptr, nullptr).error);
 
-  payload_router.set_active(true);
+  payload_router.SetActive(true);
   EXPECT_CALL(rtp, SendOutgoingData(encoded_image._frameType, payload_type,
                                     encoded_image._timeStamp,
                                     encoded_image.capture_time_ms_, &payload,
@@ -60,7 +60,7 @@
       EncodedImageCallback::Result::OK,
       payload_router.OnEncodedImage(encoded_image, nullptr, nullptr).error);
 
-  payload_router.set_active(false);
+  payload_router.SetActive(false);
   EXPECT_CALL(rtp, SendOutgoingData(encoded_image._frameType, payload_type,
                                     encoded_image._timeStamp,
                                     encoded_image.capture_time_ms_, &payload,
@@ -70,7 +70,7 @@
       EncodedImageCallback::Result::OK,
       payload_router.OnEncodedImage(encoded_image, nullptr, nullptr).error);
 
-  payload_router.set_active(true);
+  payload_router.SetActive(true);
   EXPECT_CALL(rtp, SendOutgoingData(encoded_image._frameType, payload_type,
                                     encoded_image._timeStamp,
                                     encoded_image.capture_time_ms_, &payload,
@@ -106,7 +106,7 @@
   codec_info_1.codecType = kVideoCodecVP8;
   codec_info_1.codecSpecific.VP8.simulcastIdx = 0;
 
-  payload_router.set_active(true);
+  payload_router.SetActive(true);
   EXPECT_CALL(rtp_1, SendOutgoingData(encoded_image._frameType, payload_type,
                                       encoded_image._timeStamp,
                                       encoded_image.capture_time_ms_, &payload,
@@ -136,7 +136,7 @@
                 .error);
 
   // Inactive.
-  payload_router.set_active(false);
+  payload_router.SetActive(false);
   EXPECT_CALL(rtp_1, SendOutgoingData(_, _, _, _, _, _, _, _, _))
       .Times(0);
   EXPECT_CALL(rtp_2, SendOutgoingData(_, _, _, _, _, _, _, _, _))
@@ -182,4 +182,52 @@
       .WillOnce(Return(kTestMinPayloadLength));
   EXPECT_EQ(kTestMinPayloadLength, payload_router.MaxPayloadLength());
 }
+
+TEST(PayloadRouterTest, SimulcastTargetBitrate) {
+  NiceMock<MockRtpRtcp> rtp_1;
+  NiceMock<MockRtpRtcp> rtp_2;
+  std::vector<RtpRtcp*> modules;
+  modules.push_back(&rtp_1);
+  modules.push_back(&rtp_2);
+  PayloadRouter payload_router(modules, 42);
+  payload_router.SetActive(true);
+
+  BitrateAllocation bitrate;
+  bitrate.SetBitrate(0, 0, 10000);
+  bitrate.SetBitrate(0, 1, 20000);
+  bitrate.SetBitrate(1, 0, 40000);
+  bitrate.SetBitrate(1, 1, 80000);
+
+  BitrateAllocation layer0_bitrate;
+  layer0_bitrate.SetBitrate(0, 0, 10000);
+  layer0_bitrate.SetBitrate(0, 1, 20000);
+
+  BitrateAllocation layer1_bitrate;
+  layer1_bitrate.SetBitrate(0, 0, 40000);
+  layer1_bitrate.SetBitrate(0, 1, 80000);
+
+  EXPECT_CALL(rtp_1, SetVideoBitrateAllocation(layer0_bitrate)).Times(1);
+  EXPECT_CALL(rtp_2, SetVideoBitrateAllocation(layer1_bitrate)).Times(1);
+
+  payload_router.OnBitrateAllocationUpdated(bitrate);
+}
+
+TEST(PayloadRouterTest, SvcTargetBitrate) {
+  NiceMock<MockRtpRtcp> rtp_1;
+  std::vector<RtpRtcp*> modules;
+  modules.push_back(&rtp_1);
+  PayloadRouter payload_router(modules, 42);
+  payload_router.SetActive(true);
+
+  BitrateAllocation bitrate;
+  bitrate.SetBitrate(0, 0, 10000);
+  bitrate.SetBitrate(0, 1, 20000);
+  bitrate.SetBitrate(1, 0, 40000);
+  bitrate.SetBitrate(1, 1, 80000);
+
+  EXPECT_CALL(rtp_1, SetVideoBitrateAllocation(bitrate)).Times(1);
+
+  payload_router.OnBitrateAllocationUpdated(bitrate);
+}
+
 }  // namespace webrtc
diff --git a/webrtc/video/video_send_stream.cc b/webrtc/video/video_send_stream.cc
index a1c1a0b..188854a 100644
--- a/webrtc/video/video_send_stream.cc
+++ b/webrtc/video/video_send_stream.cc
@@ -17,6 +17,7 @@
 #include <vector>
 
 #include "webrtc/common_types.h"
+#include "webrtc/common_video/include/video_bitrate_allocator.h"
 #include "webrtc/base/checks.h"
 #include "webrtc/base/file.h"
 #include "webrtc/base/logging.h"
@@ -289,7 +290,8 @@
 class VideoSendStreamImpl : public webrtc::BitrateAllocatorObserver,
                             public webrtc::OverheadObserver,
                             public webrtc::VCMProtectionCallback,
-                            public ViEEncoder::EncoderSink {
+                            public ViEEncoder::EncoderSink,
+                            public VideoBitrateAllocationObserver {
  public:
   VideoSendStreamImpl(SendStatisticsProxy* stats_proxy,
                       rtc::TaskQueue* worker_queue,
@@ -357,6 +359,9 @@
       const CodecSpecificInfo* codec_specific_info,
       const RTPFragmentationHeader* fragmentation) override;
 
+  // Implements VideoBitrateAllocationObserver.
+  void OnBitrateAllocationUpdated(const BitrateAllocation& allocation) override;
+
   void ConfigureProtection();
   void ConfigureSsrcs();
   void SignalEncoderTimedOut();
@@ -598,7 +603,6 @@
   vie_encoder_.reset(new ViEEncoder(
       num_cpu_cores, &stats_proxy_, config_.encoder_settings,
       config_.pre_encode_callback, config_.post_encode_callback));
-
   worker_queue_->PostTask(std::unique_ptr<rtc::QueuedTask>(new ConstructionTask(
       &send_stream_, &thread_sync_event_, &stats_proxy_, vie_encoder_.get(),
       module_process_thread, call_stats, congestion_controller, packet_router,
@@ -610,7 +614,7 @@
   // it was created on.
   thread_sync_event_.Wait(rtc::Event::kForever);
   send_stream_->RegisterProcessThread(module_process_thread);
-
+  vie_encoder_->SetBitrateObserver(send_stream_.get());
   vie_encoder_->RegisterProcessThread(module_process_thread);
 
   ReconfigureVideoEncoder(std::move(encoder_config));
@@ -849,7 +853,7 @@
 
 VideoSendStreamImpl::~VideoSendStreamImpl() {
   RTC_DCHECK_RUN_ON(worker_queue_);
-  RTC_DCHECK(!payload_router_.active())
+  RTC_DCHECK(!payload_router_.IsActive())
       << "VideoSendStreamImpl::Stop not called";
   LOG(LS_INFO) << "~VideoSendStreamInternal: " << config_->ToString();
 
@@ -873,10 +877,10 @@
 void VideoSendStreamImpl::Start() {
   RTC_DCHECK_RUN_ON(worker_queue_);
   LOG(LS_INFO) << "VideoSendStream::Start";
-  if (payload_router_.active())
+  if (payload_router_.IsActive())
     return;
   TRACE_EVENT_INSTANT0("webrtc", "VideoSendStream::Start");
-  payload_router_.set_active(true);
+  payload_router_.SetActive(true);
 
   bitrate_allocator_->AddObserver(
       this, encoder_min_bitrate_bps_, encoder_max_bitrate_bps_,
@@ -898,10 +902,10 @@
 void VideoSendStreamImpl::Stop() {
   RTC_DCHECK_RUN_ON(worker_queue_);
   LOG(LS_INFO) << "VideoSendStream::Stop";
-  if (!payload_router_.active())
+  if (!payload_router_.IsActive())
     return;
   TRACE_EVENT_INSTANT0("webrtc", "VideoSendStream::Stop");
-  payload_router_.set_active(false);
+  payload_router_.SetActive(false);
   bitrate_allocator_->RemoveObserver(this);
   {
     rtc::CritScope lock(&encoder_activity_crit_sect_);
@@ -923,6 +927,11 @@
   }
 }
 
+void VideoSendStreamImpl::OnBitrateAllocationUpdated(
+    const BitrateAllocation& allocation) {
+  payload_router_.OnBitrateAllocationUpdated(allocation);
+}
+
 void VideoSendStreamImpl::SignalEncoderActive() {
   RTC_DCHECK_RUN_ON(worker_queue_);
   LOG(LS_INFO) << "SignalEncoderActive, Encoder is active.";
@@ -965,7 +974,7 @@
       streams[0].width, streams[0].height, number_of_temporal_layers,
       config_->rtp.max_packet_size);
 
-  if (payload_router_.active()) {
+  if (payload_router_.IsActive()) {
     // The send stream is started already. Update the allocator with new bitrate
     // limits.
     bitrate_allocator_->AddObserver(
@@ -1174,7 +1183,7 @@
                                                int64_t rtt,
                                                int64_t probing_interval_ms) {
   RTC_DCHECK_RUN_ON(worker_queue_);
-  RTC_DCHECK(payload_router_.active())
+  RTC_DCHECK(payload_router_.IsActive())
       << "VideoSendStream::Start has not been called.";
 
   if (webrtc::field_trial::FindFullName("WebRTC-SendSideBwe-WithOverhead") ==
diff --git a/webrtc/video/vie_encoder.cc b/webrtc/video/vie_encoder.cc
index 343cd4c..de6b9a8 100644
--- a/webrtc/video/vie_encoder.cc
+++ b/webrtc/video/vie_encoder.cc
@@ -19,6 +19,7 @@
 #include "webrtc/base/logging.h"
 #include "webrtc/base/trace_event.h"
 #include "webrtc/base/timeutils.h"
+#include "webrtc/common_video/include/video_bitrate_allocator.h"
 #include "webrtc/modules/pacing/paced_sender.h"
 #include "webrtc/modules/video_coding/codecs/vp8/temporal_layers.h"
 #include "webrtc/modules/video_coding/include/video_coding.h"
@@ -26,7 +27,6 @@
 #include "webrtc/video/overuse_frame_detector.h"
 #include "webrtc/video/send_statistics_proxy.h"
 #include "webrtc/video_frame.h"
-
 namespace webrtc {
 
 namespace {
@@ -270,6 +270,7 @@
       last_frame_log_ms_(clock_->TimeInMilliseconds()),
       captured_frame_count_(0),
       dropped_frame_count_(0),
+      bitrate_observer_(nullptr),
       encoder_queue_("EncoderQueue") {
   encoder_queue_.PostTask([this] {
     RTC_DCHECK_RUN_ON(&encoder_queue_);
@@ -292,6 +293,7 @@
     RTC_DCHECK_RUN_ON(&encoder_queue_);
     overuse_detector_.StopCheckForOveruse();
     rate_allocator_.reset();
+    bitrate_observer_ = nullptr;
     video_sender_.RegisterExternalEncoder(nullptr, settings_.payload_type,
                                           false);
     quality_scaler_ = nullptr;
@@ -314,6 +316,16 @@
   module_process_thread_->DeRegisterModule(&video_sender_);
 }
 
+void ViEEncoder::SetBitrateObserver(
+    VideoBitrateAllocationObserver* bitrate_observer) {
+  RTC_DCHECK_RUN_ON(&thread_checker_);
+  encoder_queue_.PostTask([this, bitrate_observer] {
+    RTC_DCHECK_RUN_ON(&encoder_queue_);
+    RTC_DCHECK(!bitrate_observer_);
+    bitrate_observer_ = bitrate_observer;
+  });
+}
+
 void ViEEncoder::SetSource(
     rtc::VideoSourceInterface<VideoFrame>* source,
     const VideoSendStream::DegradationPreference& degradation_preference) {
@@ -405,7 +417,9 @@
     RTC_DCHECK(success);
   }
 
-  video_sender_.UpdateChannelParemeters(rate_allocator_.get());
+  video_sender_.UpdateChannelParemeters(rate_allocator_.get(),
+                                        bitrate_observer_);
+
   if (stats_proxy_) {
     int framerate = stats_proxy_->GetSendFrameRate();
     if (framerate == 0)
@@ -660,7 +674,8 @@
                   << " rtt " << round_trip_time_ms;
 
   video_sender_.SetChannelParameters(bitrate_bps, fraction_lost,
-                                     round_trip_time_ms, rate_allocator_.get());
+                                     round_trip_time_ms, rate_allocator_.get(),
+                                     bitrate_observer_);
 
   encoder_start_bitrate_bps_ =
       bitrate_bps != 0 ? bitrate_bps : encoder_start_bitrate_bps_;
diff --git a/webrtc/video/vie_encoder.h b/webrtc/video/vie_encoder.h
index 7884bbe..5ad1ff7 100644
--- a/webrtc/video/vie_encoder.h
+++ b/webrtc/video/vie_encoder.h
@@ -37,6 +37,7 @@
 
 class ProcessThread;
 class SendStatisticsProxy;
+class VideoBitrateAllocationObserver;
 
 // VieEncoder represent a video encoder that accepts raw video frames as input
 // and produces an encoded bit stream.
@@ -91,6 +92,8 @@
   // TODO(perkj): Can we remove VideoCodec.startBitrate ?
   void SetStartBitrate(int start_bitrate_bps);
 
+  void SetBitrateObserver(VideoBitrateAllocationObserver* bitrate_observer);
+
   void ConfigureEncoder(VideoEncoderConfig config,
                         size_t max_data_payload_length,
                         bool nack_enabled);
@@ -231,6 +234,8 @@
   int captured_frame_count_ ACCESS_ON(&encoder_queue_);
   int dropped_frame_count_ ACCESS_ON(&encoder_queue_);
 
+  VideoBitrateAllocationObserver* bitrate_observer_ ACCESS_ON(&encoder_queue_);
+
   // All public methods are proxied to |encoder_queue_|. It must must be
   // destroyed first to make sure no tasks are run that use other members.
   rtc::TaskQueue encoder_queue_;