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/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_;