Wire up target_media_bitrate in VideoSendStream.

Also wires up target_enc_bitrate in WebRtcVideoEngine2.

BUG=1667,1788
R=mflodman@webrtc.org, stefan@webrtc.org

Review URL: https://webrtc-codereview.appspot.com/42479004

Cr-Commit-Position: refs/heads/master@{#8515}
git-svn-id: http://webrtc.googlecode.com/svn/trunk@8515 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/talk/media/webrtc/webrtcvideoengine2.cc b/talk/media/webrtc/webrtcvideoengine2.cc
index 5a380cb..9006934 100644
--- a/talk/media/webrtc/webrtcvideoengine2.cc
+++ b/talk/media/webrtc/webrtcvideoengine2.cc
@@ -1825,6 +1825,7 @@
     bwe_info->transmit_bitrate += it->second.total_bitrate_bps;
     bwe_info->retransmit_bitrate += it->second.retransmit_bitrate_bps;
   }
+  bwe_info->target_enc_bitrate += stats.target_media_bitrate_bps;
   bwe_info->actual_enc_bitrate += stats.media_bitrate_bps;
 }
 
diff --git a/talk/media/webrtc/webrtcvideoengine2_unittest.cc b/talk/media/webrtc/webrtcvideoengine2_unittest.cc
index 751765d..283ade1 100644
--- a/talk/media/webrtc/webrtcvideoengine2_unittest.cc
+++ b/talk/media/webrtc/webrtcvideoengine2_unittest.cc
@@ -2224,6 +2224,7 @@
 TEST_F(WebRtcVideoChannel2Test, TranslatesSenderBitrateStatsCorrectly) {
   FakeVideoSendStream* stream = AddSendStream();
   webrtc::VideoSendStream::Stats stats;
+  stats.target_media_bitrate_bps = 156;
   stats.media_bitrate_bps = 123;
   stats.substreams[17].total_bitrate_bps = 1;
   stats.substreams[17].retransmit_bitrate_bps = 2;
@@ -2233,6 +2234,7 @@
 
   FakeVideoSendStream* stream2 = AddSendStream();
   webrtc::VideoSendStream::Stats stats2;
+  stats2.target_media_bitrate_bps = 200;
   stats2.media_bitrate_bps = 321;
   stats2.substreams[13].total_bitrate_bps = 5;
   stats2.substreams[13].retransmit_bitrate_bps = 6;
@@ -2247,6 +2249,8 @@
   // is OK as std::maps are sorted and AddSendStream() gives increasing SSRCs.
   EXPECT_EQ(stats.media_bitrate_bps, info.senders[0].nominal_bitrate);
   EXPECT_EQ(stats2.media_bitrate_bps, info.senders[1].nominal_bitrate);
+  EXPECT_EQ(stats.target_media_bitrate_bps + stats2.target_media_bitrate_bps,
+            info.bw_estimations[0].target_enc_bitrate);
   EXPECT_EQ(stats.media_bitrate_bps + stats2.media_bitrate_bps,
             info.bw_estimations[0].actual_enc_bitrate);
   EXPECT_EQ(1 + 3 + 5 + 7, info.bw_estimations[0].transmit_bitrate)
diff --git a/webrtc/modules/utility/source/video_coder.cc b/webrtc/modules/utility/source/video_coder.cc
index 2aff128..78a99f0 100644
--- a/webrtc/modules/utility/source/video_coder.cc
+++ b/webrtc/modules/utility/source/video_coder.cc
@@ -14,7 +14,8 @@
 #include "webrtc/modules/video_coding/main/source/encoded_frame.h"
 
 namespace webrtc {
-VideoCoder::VideoCoder() : _vcm(VideoCodingModule::Create()), _decodedVideo(0) {
+VideoCoder::VideoCoder()
+    : _vcm(VideoCodingModule::Create(nullptr)), _decodedVideo(0) {
     _vcm->InitializeSender();
     _vcm->InitializeReceiver();
 
diff --git a/webrtc/modules/video_coding/main/interface/video_coding.h b/webrtc/modules/video_coding/main/interface/video_coding.h
index 2371685..859f285 100644
--- a/webrtc/modules/video_coding/main/interface/video_coding.h
+++ b/webrtc/modules/video_coding/main/interface/video_coding.h
@@ -81,7 +81,8 @@
         kReferenceSelection
     };
 
-    static VideoCodingModule* Create();
+    static VideoCodingModule* Create(
+        VideoEncoderRateObserver* encoder_rate_observer);
 
     static VideoCodingModule* Create(Clock* clock, EventFactory* event_factory);
 
diff --git a/webrtc/modules/video_coding/main/interface/video_coding_defines.h b/webrtc/modules/video_coding/main/interface/video_coding_defines.h
index 976a176..ea47e31 100644
--- a/webrtc/modules/video_coding/main/interface/video_coding_defines.h
+++ b/webrtc/modules/video_coding/main/interface/video_coding_defines.h
@@ -148,6 +148,12 @@
   }
 };
 
+class VideoEncoderRateObserver {
+ public:
+  virtual ~VideoEncoderRateObserver() {}
+  virtual void OnSetRates(uint32_t bitrate_bps, int framerate) = 0;
+};
+
 // Callback class used for telling the user about what frame type needed to continue decoding.
 // Typically a key frame when the stream has been corrupted in some way.
 class VCMFrameTypeCallback {
diff --git a/webrtc/modules/video_coding/main/source/codec_database.cc b/webrtc/modules/video_coding/main/source/codec_database.cc
index e498054..6ca7d9d 100644
--- a/webrtc/modules/video_coding/main/source/codec_database.cc
+++ b/webrtc/modules/video_coding/main/source/codec_database.cc
@@ -93,7 +93,8 @@
       internal_render_timing(internal_render_timing) {
 }
 
-VCMCodecDataBase::VCMCodecDataBase()
+VCMCodecDataBase::VCMCodecDataBase(
+    VideoEncoderRateObserver* encoder_rate_observer)
     : number_of_cores_(0),
       max_payload_size_(kDefaultPayloadSize),
       periodic_key_frames_(false),
@@ -104,11 +105,13 @@
       external_payload_type_(0),
       external_encoder_(NULL),
       internal_source_(false),
+      encoder_rate_observer_(encoder_rate_observer),
       ptr_encoder_(NULL),
       ptr_decoder_(NULL),
       current_dec_is_external_(false),
       dec_map_(),
-      dec_external_map_() {}
+      dec_external_map_() {
+}
 
 VCMCodecDataBase::~VCMCodecDataBase() {
   ResetSender();
@@ -295,7 +298,8 @@
   DeleteEncoder();
   if (send_codec->plType == external_payload_type_) {
     // External encoder.
-    ptr_encoder_ = new VCMGenericEncoder(*external_encoder_, internal_source_);
+    ptr_encoder_ = new VCMGenericEncoder(
+        external_encoder_, encoder_rate_observer_, internal_source_);
     current_enc_is_external_ = true;
   } else {
     ptr_encoder_ = CreateEncoder(send_codec->codecType);
@@ -679,15 +683,18 @@
   switch (type) {
 #ifdef VIDEOCODEC_VP8
     case kVideoCodecVP8:
-      return new VCMGenericEncoder(*(VP8Encoder::Create()));
+      return new VCMGenericEncoder(VP8Encoder::Create(), encoder_rate_observer_,
+                                   false);
 #endif
 #ifdef VIDEOCODEC_VP9
     case kVideoCodecVP9:
-      return new VCMGenericEncoder(*(VP9Encoder::Create()));
+      return new VCMGenericEncoder(VP9Encoder::Create(), encoder_rate_observer_,
+                                   false);
 #endif
 #ifdef VIDEOCODEC_I420
     case kVideoCodecI420:
-      return new VCMGenericEncoder(*(new I420Encoder));
+      return new VCMGenericEncoder(new I420Encoder(), encoder_rate_observer_,
+                                   false);
 #endif
     default:
       LOG(LS_WARNING) << "No internal encoder of this type exists.";
@@ -698,9 +705,8 @@
 void VCMCodecDataBase::DeleteEncoder() {
   if (ptr_encoder_) {
     ptr_encoder_->Release();
-    if (!current_enc_is_external_) {
-      delete &ptr_encoder_->_encoder;
-    }
+    if (!current_enc_is_external_)
+      delete ptr_encoder_->encoder_;
     delete ptr_encoder_;
     ptr_encoder_ = NULL;
   }
diff --git a/webrtc/modules/video_coding/main/source/codec_database.h b/webrtc/modules/video_coding/main/source/codec_database.h
index a31decb..1aa8f4d 100644
--- a/webrtc/modules/video_coding/main/source/codec_database.h
+++ b/webrtc/modules/video_coding/main/source/codec_database.h
@@ -46,7 +46,7 @@
 
 class VCMCodecDataBase {
  public:
-  VCMCodecDataBase();
+  explicit VCMCodecDataBase(VideoEncoderRateObserver* encoder_rate_observer);
   ~VCMCodecDataBase();
 
   // Sender Side
@@ -180,6 +180,7 @@
   uint8_t external_payload_type_;
   VideoEncoder* external_encoder_;
   bool internal_source_;
+  VideoEncoderRateObserver* const encoder_rate_observer_;
   VCMGenericEncoder* ptr_encoder_;
   VCMGenericDecoder* ptr_decoder_;
   bool current_dec_is_external_;
diff --git a/webrtc/modules/video_coding/main/source/generic_encoder.cc b/webrtc/modules/video_coding/main/source/generic_encoder.cc
index d01fbf4..208f925 100644
--- a/webrtc/modules/video_coding/main/source/generic_encoder.cc
+++ b/webrtc/modules/video_coding/main/source/generic_encoder.cc
@@ -55,18 +55,18 @@
 
 //#define DEBUG_ENCODER_BIT_STREAM
 
-VCMGenericEncoder::VCMGenericEncoder(VideoEncoder& encoder, bool internalSource /*= false*/)
-:
-_encoder(encoder),
-_codecType(kVideoCodecUnknown),
-_VCMencodedFrameCallback(NULL),
-_bitRate(0),
-_frameRate(0),
-_internalSource(internalSource)
-{
+VCMGenericEncoder::VCMGenericEncoder(VideoEncoder* encoder,
+                                     VideoEncoderRateObserver* rate_observer,
+                                     bool internalSource)
+    : encoder_(encoder),
+      rate_observer_(rate_observer),
+      _codecType(kVideoCodecUnknown),
+      _VCMencodedFrameCallback(NULL),
+      _bitRate(0),
+      _frameRate(0),
+      _internalSource(internalSource) {
 }
 
-
 VCMGenericEncoder::~VCMGenericEncoder()
 {
 }
@@ -76,7 +76,7 @@
     _bitRate = 0;
     _frameRate = 0;
     _VCMencodedFrameCallback = NULL;
-    return _encoder.Release();
+    return encoder_->Release();
 }
 
 int32_t
@@ -87,7 +87,7 @@
     _bitRate = settings->startBitrate * 1000;
     _frameRate = settings->maxFramerate;
     _codecType = settings->codecType;
-    if (_encoder.InitEncode(settings, numberOfCores, maxPayloadSize) != 0) {
+    if (encoder_->InitEncode(settings, numberOfCores, maxPayloadSize) != 0) {
       LOG(LS_ERROR) << "Failed to initialize the encoder associated with "
                        "payload name: " << settings->plName;
       return -1;
@@ -102,33 +102,35 @@
   std::vector<VideoFrameType> video_frame_types(frameTypes.size(),
                                                 kDeltaFrame);
   VCMEncodedFrame::ConvertFrameTypes(frameTypes, &video_frame_types);
-  return _encoder.Encode(inputFrame, codecSpecificInfo, &video_frame_types);
+  return encoder_->Encode(inputFrame, codecSpecificInfo, &video_frame_types);
 }
 
 int32_t
 VCMGenericEncoder::SetChannelParameters(int32_t packetLoss, int64_t rtt)
 {
-    return _encoder.SetChannelParameters(packetLoss, rtt);
+    return encoder_->SetChannelParameters(packetLoss, rtt);
 }
 
 int32_t
 VCMGenericEncoder::SetRates(uint32_t newBitRate, uint32_t frameRate)
 {
     uint32_t target_bitrate_kbps = (newBitRate + 500) / 1000;
-    int32_t ret = _encoder.SetRates(target_bitrate_kbps, frameRate);
+    int32_t ret = encoder_->SetRates(target_bitrate_kbps, frameRate);
     if (ret < 0)
     {
         return ret;
     }
     _bitRate = newBitRate;
     _frameRate = frameRate;
+    if (rate_observer_ != nullptr)
+      rate_observer_->OnSetRates(newBitRate, frameRate);
     return VCM_OK;
 }
 
 int32_t
 VCMGenericEncoder::CodecConfigParameters(uint8_t* buffer, int32_t size)
 {
-    int32_t ret = _encoder.CodecConfigParameters(buffer, size);
+    int32_t ret = encoder_->CodecConfigParameters(buffer, size);
     if (ret < 0)
     {
         return ret;
@@ -149,7 +151,7 @@
 int32_t
 VCMGenericEncoder::SetPeriodicKeyFrames(bool enable)
 {
-    return _encoder.SetPeriodicKeyFrames(enable);
+    return encoder_->SetPeriodicKeyFrames(enable);
 }
 
 int32_t VCMGenericEncoder::RequestFrame(
@@ -158,7 +160,7 @@
   std::vector<VideoFrameType> video_frame_types(frame_types.size(),
                                                 kDeltaFrame);
   VCMEncodedFrame::ConvertFrameTypes(frame_types, &video_frame_types);
-  return _encoder.Encode(image, NULL, &video_frame_types);
+  return encoder_->Encode(image, NULL, &video_frame_types);
 }
 
 int32_t
@@ -166,7 +168,7 @@
 {
    _VCMencodedFrameCallback = VCMencodedFrameCallback;
    _VCMencodedFrameCallback->SetInternalSource(_internalSource);
-   return _encoder.RegisterEncodeCompleteCallback(_VCMencodedFrameCallback);
+   return encoder_->RegisterEncodeCompleteCallback(_VCMencodedFrameCallback);
 }
 
 bool
diff --git a/webrtc/modules/video_coding/main/source/generic_encoder.h b/webrtc/modules/video_coding/main/source/generic_encoder.h
index 70569fa..e547a47 100644
--- a/webrtc/modules/video_coding/main/source/generic_encoder.h
+++ b/webrtc/modules/video_coding/main/source/generic_encoder.h
@@ -12,6 +12,7 @@
 #define WEBRTC_MODULES_VIDEO_CODING_GENERIC_ENCODER_H_
 
 #include "webrtc/modules/video_coding/codecs/interface/video_codec_interface.h"
+#include "webrtc/modules/video_coding/main/interface/video_coding_defines.h"
 
 #include <stdio.h>
 
@@ -73,7 +74,9 @@
 {
     friend class VCMCodecDataBase;
 public:
-    VCMGenericEncoder(VideoEncoder& encoder, bool internalSource = false);
+ VCMGenericEncoder(VideoEncoder* encoder,
+                   VideoEncoderRateObserver* rate_observer,
+                   bool internalSource);
     ~VCMGenericEncoder();
     /**
     * Free encoder memory
@@ -127,7 +130,8 @@
     bool InternalSource() const;
 
 private:
-    VideoEncoder&               _encoder;
+    VideoEncoder* const encoder_;
+    VideoEncoderRateObserver* const rate_observer_;
     VideoCodecType              _codecType;
     VCMEncodedFrameCallback*    _VCMencodedFrameCallback;
     uint32_t                    _bitRate;
diff --git a/webrtc/modules/video_coding/main/source/video_coding_impl.cc b/webrtc/modules/video_coding/main/source/video_coding_impl.cc
index 89eb29b..eab45f0 100644
--- a/webrtc/modules/video_coding/main/source/video_coding_impl.cc
+++ b/webrtc/modules/video_coding/main/source/video_coding_impl.cc
@@ -73,9 +73,12 @@
  public:
   VideoCodingModuleImpl(Clock* clock,
                         EventFactory* event_factory,
-                        bool owns_event_factory)
+                        bool owns_event_factory,
+                        VideoEncoderRateObserver* encoder_rate_observer)
       : VideoCodingModule(),
-        sender_(new vcm::VideoSender(clock, &post_encode_callback_)),
+        sender_(new vcm::VideoSender(clock,
+                                     &post_encode_callback_,
+                                     encoder_rate_observer)),
         receiver_(new vcm::VideoReceiver(clock, event_factory)),
         own_event_factory_(owns_event_factory ? event_factory : NULL) {}
 
@@ -383,16 +386,19 @@
   return VCMCodecDataBase::Codec(codecType, codec) ? 0 : -1;
 }
 
-VideoCodingModule* VideoCodingModule::Create() {
-  return new VideoCodingModuleImpl(
-      Clock::GetRealTimeClock(), new EventFactoryImpl, true);
+VideoCodingModule* VideoCodingModule::Create(
+    VideoEncoderRateObserver* encoder_rate_observer) {
+  return new VideoCodingModuleImpl(Clock::GetRealTimeClock(),
+                                   new EventFactoryImpl, true,
+                                   encoder_rate_observer);
 }
 
-VideoCodingModule* VideoCodingModule::Create(Clock* clock,
-                                             EventFactory* event_factory) {
+VideoCodingModule* VideoCodingModule::Create(
+    Clock* clock,
+    EventFactory* event_factory) {
   assert(clock);
   assert(event_factory);
-  return new VideoCodingModuleImpl(clock, event_factory, false);
+  return new VideoCodingModuleImpl(clock, event_factory, false, nullptr);
 }
 
 void VideoCodingModule::Destroy(VideoCodingModule* module) {
diff --git a/webrtc/modules/video_coding/main/source/video_coding_impl.h b/webrtc/modules/video_coding/main/source/video_coding_impl.h
index ed38bd5..8faa1e4 100644
--- a/webrtc/modules/video_coding/main/source/video_coding_impl.h
+++ b/webrtc/modules/video_coding/main/source/video_coding_impl.h
@@ -56,7 +56,9 @@
  public:
   typedef VideoCodingModule::SenderNackMode SenderNackMode;
 
-  VideoSender(Clock* clock, EncodedImageCallback* post_encode_callback);
+  VideoSender(Clock* clock,
+              EncodedImageCallback* post_encode_callback,
+              VideoEncoderRateObserver* encoder_rate_observer);
 
   ~VideoSender();
 
diff --git a/webrtc/modules/video_coding/main/source/video_receiver.cc b/webrtc/modules/video_coding/main/source/video_receiver.cc
index 3e20ed3..4411e11 100644
--- a/webrtc/modules/video_coding/main/source/video_receiver.cc
+++ b/webrtc/modules/video_coding/main/source/video_receiver.cc
@@ -46,7 +46,7 @@
       _scheduleKeyRequest(false),
       max_nack_list_size_(0),
       pre_decode_image_callback_(NULL),
-      _codecDataBase(),
+      _codecDataBase(NULL),
       _receiveStatsTimer(1000, clock_),
       _retransmissionTimer(10, clock_),
       _keyRequestTimer(500, clock_) {
diff --git a/webrtc/modules/video_coding/main/source/video_sender.cc b/webrtc/modules/video_coding/main/source/video_sender.cc
index 24240e2..a805045 100644
--- a/webrtc/modules/video_coding/main/source/video_sender.cc
+++ b/webrtc/modules/video_coding/main/source/video_sender.cc
@@ -60,7 +60,8 @@
 };
 
 VideoSender::VideoSender(Clock* clock,
-                         EncodedImageCallback* post_encode_callback)
+                         EncodedImageCallback* post_encode_callback,
+                         VideoEncoderRateObserver* encoder_rate_observer)
     : clock_(clock),
       recorder_(new DebugRecorder()),
       process_crit_sect_(CriticalSectionWrapper::CreateCriticalSection()),
@@ -70,7 +71,7 @@
       _nextFrameTypes(1, kVideoFrameDelta),
       _mediaOpt(clock_),
       _sendStatsCallback(NULL),
-      _codecDataBase(),
+      _codecDataBase(encoder_rate_observer),
       frame_dropper_enabled_(true),
       _sendStatsTimer(1000, clock_),
       current_codec_(),
diff --git a/webrtc/modules/video_coding/main/source/video_sender_unittest.cc b/webrtc/modules/video_coding/main/source/video_sender_unittest.cc
index c9d6648..4be71ab 100644
--- a/webrtc/modules/video_coding/main/source/video_sender_unittest.cc
+++ b/webrtc/modules/video_coding/main/source/video_sender_unittest.cc
@@ -172,7 +172,7 @@
   TestVideoSender() : clock_(1000), packetization_callback_(&clock_) {}
 
   virtual void SetUp() OVERRIDE {
-    sender_.reset(new VideoSender(&clock_, &post_encode_callback_));
+    sender_.reset(new VideoSender(&clock_, &post_encode_callback_, nullptr));
     EXPECT_EQ(0, sender_->InitializeSender());
     EXPECT_EQ(0, sender_->RegisterTransportCallback(&packetization_callback_));
   }
diff --git a/webrtc/modules/video_coding/main/test/codec_database_test.cc b/webrtc/modules/video_coding/main/test/codec_database_test.cc
index ca269b3..07342de 100644
--- a/webrtc/modules/video_coding/main/test/codec_database_test.cc
+++ b/webrtc/modules/video_coding/main/test/codec_database_test.cc
@@ -29,7 +29,7 @@
 
 int CodecDataBaseTest::RunTest(CmdArgs& args)
 {
-    VideoCodingModule* vcm = VideoCodingModule::Create();
+    VideoCodingModule* vcm = VideoCodingModule::Create(nullptr);
     CodecDataBaseTest* cdbt = new CodecDataBaseTest(vcm);
     cdbt->Perform(args);
     VideoCodingModule::Destroy(vcm);
diff --git a/webrtc/modules/video_coding/main/test/media_opt_test.cc b/webrtc/modules/video_coding/main/test/media_opt_test.cc
index f3b1cf0..4d4ff4c 100644
--- a/webrtc/modules/video_coding/main/test/media_opt_test.cc
+++ b/webrtc/modules/video_coding/main/test/media_opt_test.cc
@@ -32,7 +32,7 @@
     Trace::CreateTrace();
     Trace::SetTraceFile((test::OutputPath() + "mediaOptTestTrace.txt").c_str());
     Trace::set_level_filter(webrtc::kTraceAll);
-    VideoCodingModule* vcm = VideoCodingModule::Create();
+    VideoCodingModule* vcm = VideoCodingModule::Create(nullptr);
     Clock* clock = Clock::GetRealTimeClock();
     MediaOptTest* mot = new MediaOptTest(vcm, clock);
     if (testNum == 0)
diff --git a/webrtc/modules/video_coding/main/test/mt_rx_tx_test.cc b/webrtc/modules/video_coding/main/test/mt_rx_tx_test.cc
index d7beb46..acbc5c9 100644
--- a/webrtc/modules/video_coding/main/test/mt_rx_tx_test.cc
+++ b/webrtc/modules/video_coding/main/test/mt_rx_tx_test.cc
@@ -145,7 +145,7 @@
         printf("Cannot read file %s.\n", outname.c_str());
         return -1;
     }
-    VideoCodingModule* vcm = VideoCodingModule::Create();
+    VideoCodingModule* vcm = VideoCodingModule::Create(nullptr);
     RtpDataCallback dataCallback(vcm);
 
     RTPSendCompleteCallback* outgoingTransport =
diff --git a/webrtc/video/end_to_end_tests.cc b/webrtc/video/end_to_end_tests.cc
index 07e3fdc..fe2a690 100644
--- a/webrtc/video/end_to_end_tests.cc
+++ b/webrtc/video/end_to_end_tests.cc
@@ -1566,6 +1566,64 @@
   RunBaseTest(&test);
 }
 
+TEST_F(EndToEndTest, ReportsSetEncoderRates) {
+  class EncoderRateStatsTest : public test::EndToEndTest,
+                               public test::FakeEncoder {
+   public:
+    EncoderRateStatsTest()
+        : EndToEndTest(kDefaultTimeoutMs),
+          FakeEncoder(Clock::GetRealTimeClock()) {}
+
+    virtual void OnStreamsCreated(
+        VideoSendStream* send_stream,
+        const std::vector<VideoReceiveStream*>& receive_streams) override {
+      send_stream_ = send_stream;
+    }
+
+    virtual void ModifyConfigs(
+        VideoSendStream::Config* send_config,
+        std::vector<VideoReceiveStream::Config>* receive_configs,
+        VideoEncoderConfig* encoder_config) override {
+      send_config->encoder_settings.encoder = this;
+    }
+
+    int32_t SetRates(uint32_t new_target_bitrate, uint32_t framerate) override {
+      // Make sure not to trigger on any default zero bitrates.
+      if (new_target_bitrate == 0)
+        return 0;
+      CriticalSectionScoped lock(crit_.get());
+      bitrate_kbps_ = new_target_bitrate;
+      observation_complete_->Set();
+      return 0;
+    }
+
+    void PerformTest() override {
+      ASSERT_EQ(kEventSignaled, Wait())
+          << "Timed out while waiting for encoder SetRates() call.";
+      // Wait for GetStats to report a corresponding bitrate.
+      for (unsigned int i = 0; i < kDefaultTimeoutMs; ++i) {
+        VideoSendStream::Stats stats = send_stream_->GetStats();
+        {
+          CriticalSectionScoped lock(crit_.get());
+          if ((stats.target_media_bitrate_bps + 500) / 1000 ==
+              static_cast<int>(bitrate_kbps_)) {
+            return;
+          }
+        }
+        SleepMs(1);
+      }
+      FAIL()
+          << "Timed out waiting for stats reporting the currently set bitrate.";
+    }
+
+   private:
+    VideoSendStream* send_stream_;
+    uint32_t bitrate_kbps_ GUARDED_BY(crit_);
+  } test;
+
+  RunBaseTest(&test);
+}
+
 TEST_F(EndToEndTest, GetStats) {
   static const int kStartBitrateBps = 3000000;
   class StatsObserver : public test::EndToEndTest, public I420FrameCallback {
diff --git a/webrtc/video/send_statistics_proxy.cc b/webrtc/video/send_statistics_proxy.cc
index 7c148b7..33255f9 100644
--- a/webrtc/video/send_statistics_proxy.cc
+++ b/webrtc/video/send_statistics_proxy.cc
@@ -95,6 +95,11 @@
   return &stats_.substreams[ssrc];  // Insert new entry and return ptr.
 }
 
+void SendStatisticsProxy::OnSetRates(uint32_t bitrate_bps, int framerate) {
+  CriticalSectionScoped lock(crit_.get());
+  stats_.target_media_bitrate_bps = bitrate_bps;
+}
+
 void SendStatisticsProxy::OnSendEncodedImage(
     const EncodedImage& encoded_image,
     const RTPVideoHeader* rtp_video_header) {
diff --git a/webrtc/video/send_statistics_proxy.h b/webrtc/video/send_statistics_proxy.h
index 540ee32..f33df8d 100644
--- a/webrtc/video/send_statistics_proxy.h
+++ b/webrtc/video/send_statistics_proxy.h
@@ -16,6 +16,7 @@
 #include "webrtc/base/thread_annotations.h"
 #include "webrtc/common_types.h"
 #include "webrtc/modules/video_coding/codecs/interface/video_codec_interface.h"
+#include "webrtc/modules/video_coding/main/interface/video_coding_defines.h"
 #include "webrtc/system_wrappers/interface/clock.h"
 #include "webrtc/system_wrappers/interface/scoped_ptr.h"
 #include "webrtc/video_engine/include/vie_base.h"
@@ -35,6 +36,7 @@
                             public FrameCountObserver,
                             public ViEEncoderObserver,
                             public ViECaptureObserver,
+                            public VideoEncoderRateObserver,
                             public SendSideDelayObserver {
  public:
   static const int kStatsTimeoutMs;
@@ -47,6 +49,9 @@
   virtual void OnSendEncodedImage(const EncodedImage& encoded_image,
                                   const RTPVideoHeader* rtp_video_header);
 
+  // From VideoEncoderRateObserver.
+  void OnSetRates(uint32_t bitrate_bps, int framerate) override;
+
  protected:
   // From CpuOveruseMetricsObserver.
   void CpuOveruseMetricsUpdated(const CpuOveruseMetrics& metrics) OVERRIDE;
diff --git a/webrtc/video_engine/vie_channel.cc b/webrtc/video_engine/vie_channel.cc
index f857298..f958894 100644
--- a/webrtc/video_engine/vie_channel.cc
+++ b/webrtc/video_engine/vie_channel.cc
@@ -102,7 +102,7 @@
       rtp_rtcp_cs_(CriticalSectionWrapper::CreateCriticalSection()),
       send_payload_router_(new PayloadRouter()),
       vcm_protection_callback_(new ViEChannelProtectionCallback(this)),
-      vcm_(VideoCodingModule::Create()),
+      vcm_(VideoCodingModule::Create(nullptr)),
       vie_receiver_(channel_id, vcm_, remote_bitrate_estimator, this),
       vie_sender_(channel_id),
       vie_sync_(vcm_, this),
diff --git a/webrtc/video_engine/vie_encoder.cc b/webrtc/video_engine/vie_encoder.cc
index 9c105ee..0b8ce9a 100644
--- a/webrtc/video_engine/vie_encoder.cc
+++ b/webrtc/video_engine/vie_encoder.cc
@@ -136,7 +136,7 @@
   : channel_id_(channel_id),
     number_of_cores_(number_of_cores),
     disable_default_encoder_(disable_default_encoder),
-    vcm_(*webrtc::VideoCodingModule::Create()),
+    vcm_(*webrtc::VideoCodingModule::Create(this)),
     vpm_(*webrtc::VideoProcessingModule::Create(ViEModuleId(-1, channel_id))),
     send_payload_router_(NULL),
     vcm_protection_callback_(NULL),
@@ -705,6 +705,12 @@
   }
 }
 
+void ViEEncoder::OnSetRates(uint32_t bitrate_bps, int framerate) {
+  CriticalSectionScoped cs(callback_cs_.get());
+  if (send_statistics_proxy_ != nullptr)
+    send_statistics_proxy_->OnSetRates(bitrate_bps, framerate);
+}
+
 int32_t ViEEncoder::SendData(
     const uint8_t payload_type,
     const EncodedImage& encoded_image,
@@ -712,8 +718,10 @@
     const RTPVideoHeader* rtp_video_hdr) {
   DCHECK(send_payload_router_ != NULL);
 
-  if (send_statistics_proxy_ != NULL) {
-    send_statistics_proxy_->OnSendEncodedImage(encoded_image, rtp_video_hdr);
+  {
+    CriticalSectionScoped cs(callback_cs_.get());
+    if (send_statistics_proxy_ != NULL)
+      send_statistics_proxy_->OnSendEncodedImage(encoded_image, rtp_video_hdr);
   }
 
   return send_payload_router_->RoutePayload(
@@ -959,6 +967,7 @@
 
 void ViEEncoder::RegisterSendStatisticsProxy(
     SendStatisticsProxy* send_statistics_proxy) {
+  CriticalSectionScoped cs(callback_cs_.get());
   send_statistics_proxy_ = send_statistics_proxy;
 }
 
diff --git a/webrtc/video_engine/vie_encoder.h b/webrtc/video_engine/vie_encoder.h
index 2aab5f6..de264ca 100644
--- a/webrtc/video_engine/vie_encoder.h
+++ b/webrtc/video_engine/vie_encoder.h
@@ -46,6 +46,7 @@
 
 class ViEEncoder
     : public RtcpIntraFrameObserver,
+      public VideoEncoderRateObserver,
       public VCMPacketizationCallback,
       public VCMSendStatisticsCallback,
       public ViEFrameCallback {
@@ -130,6 +131,9 @@
   // Buffering mode.
   void SetSenderBufferingMode(int target_delay_ms);
 
+  // Implements VideoEncoderRateObserver.
+  void OnSetRates(uint32_t bitrate_bps, int framerate) override;
+
   // Implements VCMPacketizationCallback.
   virtual int32_t SendData(uint8_t payload_type,
                            const EncodedImage& encoded_image,
@@ -243,7 +247,7 @@
   I420FrameCallback* pre_encode_callback_ GUARDED_BY(callback_cs_);
   const int64_t start_ms_;
 
-  SendStatisticsProxy* send_statistics_proxy_;
+  SendStatisticsProxy* send_statistics_proxy_ GUARDED_BY(callback_cs_);
 };
 
 }  // namespace webrtc
diff --git a/webrtc/video_send_stream.h b/webrtc/video_send_stream.h
index eb6dfe6..c55d9e3 100644
--- a/webrtc/video_send_stream.h
+++ b/webrtc/video_send_stream.h
@@ -57,12 +57,14 @@
           encode_frame_rate(0),
           avg_encode_time_ms(0),
           encode_usage_percent(0),
+          target_media_bitrate_bps(0),
           media_bitrate_bps(0),
           suspended(false) {}
     int input_frame_rate;
     int encode_frame_rate;
     int avg_encode_time_ms;
     int encode_usage_percent;
+    int target_media_bitrate_bps;
     int media_bitrate_bps;
     bool suspended;
     std::map<uint32_t, StreamStats> substreams;