Refactoring MediaOptimization so it can easily be turned into a thread-safe class.

BUG=2732
R=stefan@webrtc.org

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

git-svn-id: http://webrtc.googlecode.com/svn/trunk@5322 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/webrtc/modules/video_coding/main/source/media_optimization.cc b/webrtc/modules/video_coding/main/source/media_optimization.cc
index 27fa681..aeffac2 100644
--- a/webrtc/modules/video_coding/main/source/media_optimization.cc
+++ b/webrtc/modules/video_coding/main/source/media_optimization.cc
@@ -17,6 +17,61 @@
 
 namespace webrtc {
 namespace media_optimization {
+namespace {
+void UpdateProtectionCallback(
+    VCMProtectionMethod* selected_method,
+    uint32_t* video_rate_bps,
+    uint32_t* nack_overhead_rate_bps,
+    uint32_t* fec_overhead_rate_bps,
+    VCMProtectionCallback* video_protection_callback) {
+  FecProtectionParams delta_fec_params;
+  FecProtectionParams key_fec_params;
+  // Get the FEC code rate for Key frames (set to 0 when NA).
+  key_fec_params.fec_rate = selected_method->RequiredProtectionFactorK();
+
+  // Get the FEC code rate for Delta frames (set to 0 when NA).
+  delta_fec_params.fec_rate = selected_method->RequiredProtectionFactorD();
+
+  // Get the FEC-UEP protection status for Key frames: UEP on/off.
+  key_fec_params.use_uep_protection = selected_method->RequiredUepProtectionK();
+
+  // Get the FEC-UEP protection status for Delta frames: UEP on/off.
+  delta_fec_params.use_uep_protection =
+      selected_method->RequiredUepProtectionD();
+
+  // The RTP module currently requires the same |max_fec_frames| for both
+  // key and delta frames.
+  delta_fec_params.max_fec_frames = selected_method->MaxFramesFec();
+  key_fec_params.max_fec_frames = selected_method->MaxFramesFec();
+
+  // Set the FEC packet mask type. |kFecMaskBursty| is more effective for
+  // consecutive losses and little/no packet re-ordering. As we currently
+  // do not have feedback data on the degree of correlated losses and packet
+  // re-ordering, we keep default setting to |kFecMaskRandom| for now.
+  delta_fec_params.fec_mask_type = kFecMaskRandom;
+  key_fec_params.fec_mask_type = kFecMaskRandom;
+
+  // TODO(Marco): Pass FEC protection values per layer.
+  video_protection_callback->ProtectionRequest(&delta_fec_params,
+                                               &key_fec_params,
+                                               video_rate_bps,
+                                               nack_overhead_rate_bps,
+                                               fec_overhead_rate_bps);
+}
+}  // namespace
+
+struct MediaOptimization::EncodedFrameSample {
+  EncodedFrameSample(int size_bytes,
+                     uint32_t timestamp,
+                     int64_t time_complete_ms)
+      : size_bytes(size_bytes),
+        timestamp(timestamp),
+        time_complete_ms(time_complete_ms) {}
+
+  uint32_t size_bytes;
+  uint32_t timestamp;
+  int64_t time_complete_ms;
+};
 
 MediaOptimization::MediaOptimization(int32_t id, Clock* clock)
     : id_(id),
@@ -35,8 +90,6 @@
       target_bit_rate_(0),
       incoming_frame_rate_(0),
       enable_qm_(false),
-      video_protection_callback_(NULL),
-      video_qmsettings_callback_(NULL),
       encoded_frame_samples_(),
       avg_sent_bit_rate_bps_(0),
       avg_sent_framerate_(0),
@@ -59,7 +112,8 @@
   loss_prot_logic_->Release();
 }
 
-int32_t MediaOptimization::Reset() {
+void MediaOptimization::Reset() {
+  SetEncodingData(kVideoCodecUnknown, 0, 0, 0, 0, 0, 0, max_payload_size_);
   memset(incoming_frame_times_, -1, sizeof(incoming_frame_times_));
   incoming_frame_rate_ = 0.0;
   frame_dropper_->Reset();
@@ -81,12 +135,52 @@
   encoded_frame_samples_.clear();
   avg_sent_bit_rate_bps_ = 0;
   num_layers_ = 1;
-  return VCM_OK;
 }
 
-uint32_t MediaOptimization::SetTargetRates(uint32_t target_bitrate,
-                                           uint8_t fraction_lost,
-                                           uint32_t round_trip_time_ms) {
+void MediaOptimization::SetEncodingData(VideoCodecType send_codec_type,
+                                        int32_t max_bit_rate,
+                                        uint32_t frame_rate,
+                                        uint32_t target_bitrate,
+                                        uint16_t width,
+                                        uint16_t height,
+                                        int num_layers,
+                                        int32_t mtu) {
+  // Everything codec specific should be reset here since this means the codec
+  // has changed. If native dimension values have changed, then either user
+  // initiated change, or QM initiated change. Will be able to determine only
+  // after the processing of the first frame.
+  last_change_time_ = clock_->TimeInMilliseconds();
+  content_->Reset();
+  content_->UpdateFrameRate(frame_rate);
+
+  max_bit_rate_ = max_bit_rate;
+  send_codec_type_ = send_codec_type;
+  target_bit_rate_ = target_bitrate;
+  float target_bitrate_kbps = static_cast<float>(target_bitrate) / 1000.0f;
+  loss_prot_logic_->UpdateBitRate(target_bitrate_kbps);
+  loss_prot_logic_->UpdateFrameRate(static_cast<float>(frame_rate));
+  loss_prot_logic_->UpdateFrameSize(width, height);
+  loss_prot_logic_->UpdateNumLayers(num_layers);
+  frame_dropper_->Reset();
+  frame_dropper_->SetRates(target_bitrate_kbps, static_cast<float>(frame_rate));
+  user_frame_rate_ = static_cast<float>(frame_rate);
+  codec_width_ = width;
+  codec_height_ = height;
+  num_layers_ = (num_layers <= 1) ? 1 : num_layers;  // Can also be zero.
+  max_payload_size_ = mtu;
+  qm_resolution_->Initialize(target_bitrate_kbps,
+                             user_frame_rate_,
+                             codec_width_,
+                             codec_height_,
+                             num_layers_);
+}
+
+uint32_t MediaOptimization::SetTargetRates(
+    uint32_t target_bitrate,
+    uint8_t fraction_lost,
+    uint32_t round_trip_time_ms,
+    VCMProtectionCallback* protection_callback,
+    VCMQMSettingsCallback* qmsettings_callback) {
   // TODO(holmer): Consider putting this threshold only on the video bitrate,
   // and not on protection.
   if (max_bit_rate_ > 0 &&
@@ -145,10 +239,13 @@
     // Get the bit cost of protection method, based on the amount of
     // overhead data actually transmitted (including headers) the last
     // second.
-    UpdateProtectionCallback(selected_method,
-                             &sent_video_rate_bps,
-                             &sent_nack_rate_bps,
-                             &sent_fec_rate_bps);
+    if (protection_callback) {
+      UpdateProtectionCallback(selected_method,
+                               &sent_video_rate_bps,
+                               &sent_nack_rate_bps,
+                               &sent_fec_rate_bps,
+                               protection_callback);
+    }
     uint32_t sent_total_rate_bps =
         sent_video_rate_bps + sent_nack_rate_bps + sent_fec_rate_bps;
     // Estimate the overhead costs of the next second as staying the same
@@ -178,7 +275,7 @@
       static_cast<float>(target_bit_rate_) / 1000.0f;
   frame_dropper_->SetRates(target_video_bitrate_kbps, incoming_frame_rate_);
 
-  if (enable_qm_) {
+  if (enable_qm_ && qmsettings_callback) {
     // Update QM with rates.
     qm_resolution_->UpdateRates(target_video_bitrate_kbps,
                                 sent_video_rate_kbps,
@@ -187,7 +284,7 @@
     // Check for QM selection.
     bool select_qm = CheckStatusForQMchange();
     if (select_qm) {
-      SelectQuality();
+      SelectQuality(qmsettings_callback);
     }
     // Reset the short-term averaged content data.
     content_->ResetShortTermAvgData();
@@ -198,44 +295,6 @@
   return target_bit_rate_;
 }
 
-int32_t MediaOptimization::SetEncodingData(VideoCodecType send_codec_type,
-                                           int32_t max_bit_rate,
-                                           uint32_t frame_rate,
-                                           uint32_t target_bitrate,
-                                           uint16_t width,
-                                           uint16_t height,
-                                           int num_layers) {
-  // Everything codec specific should be reset here since this means the codec
-  // has changed. If native dimension values have changed, then either user
-  // initiated change, or QM initiated change. Will be able to determine only
-  // after the processing of the first frame.
-  last_change_time_ = clock_->TimeInMilliseconds();
-  content_->Reset();
-  content_->UpdateFrameRate(frame_rate);
-
-  max_bit_rate_ = max_bit_rate;
-  send_codec_type_ = send_codec_type;
-  target_bit_rate_ = target_bitrate;
-  float target_bitrate_kbps = static_cast<float>(target_bitrate) / 1000.0f;
-  loss_prot_logic_->UpdateBitRate(target_bitrate_kbps);
-  loss_prot_logic_->UpdateFrameRate(static_cast<float>(frame_rate));
-  loss_prot_logic_->UpdateFrameSize(width, height);
-  loss_prot_logic_->UpdateNumLayers(num_layers);
-  frame_dropper_->Reset();
-  frame_dropper_->SetRates(target_bitrate_kbps, static_cast<float>(frame_rate));
-  user_frame_rate_ = static_cast<float>(frame_rate);
-  codec_width_ = width;
-  codec_height_ = height;
-  num_layers_ = (num_layers <= 1) ? 1 : num_layers;  // Can also be zero.
-  int32_t ret = VCM_OK;
-  ret = qm_resolution_->Initialize(target_bitrate_kbps,
-                                   user_frame_rate_,
-                                   codec_width_,
-                                   codec_height_,
-                                   num_layers_);
-  return ret;
-}
-
 void MediaOptimization::EnableProtectionMethod(bool enable,
                                                VCMProtectionMethodEnum method) {
   bool updated = false;
@@ -249,11 +308,6 @@
   }
 }
 
-bool MediaOptimization::IsProtectionMethodEnabled(
-    VCMProtectionMethodEnum method) {
-  return (loss_prot_logic_->SelectedType() == method);
-}
-
 uint32_t MediaOptimization::InputFrameRate() {
   ProcessIncomingFrameRate(clock_->TimeInMilliseconds());
   return uint32_t(incoming_frame_rate_ + 0.5f);
@@ -272,6 +326,13 @@
   return avg_sent_bit_rate_bps_;
 }
 
+VCMFrameCount MediaOptimization::SentFrameCount() {
+  VCMFrameCount count;
+  count.numDeltaFrames = delta_frame_cnt_;
+  count.numKeyFrames = key_frame_cnt_;
+  return count;
+}
+
 int32_t MediaOptimization::UpdateWithEncodedData(int encoded_length,
                                                  uint32_t timestamp,
                                                  FrameType encoded_frame_type) {
@@ -325,29 +386,14 @@
   return VCM_OK;
 }
 
-int32_t MediaOptimization::RegisterProtectionCallback(
-    VCMProtectionCallback* protection_callback) {
-  video_protection_callback_ = protection_callback;
-  return VCM_OK;
-}
-
-int32_t MediaOptimization::RegisterVideoQMCallback(
-    VCMQMSettingsCallback* video_qmsettings) {
-  video_qmsettings_callback_ = video_qmsettings;
-  // Callback setting controls QM.
-  if (video_qmsettings_callback_ != NULL) {
-    enable_qm_ = true;
-  } else {
-    enable_qm_ = false;
-  }
-  return VCM_OK;
-}
+void MediaOptimization::EnableQM(bool enable) { enable_qm_ = enable; }
 
 void MediaOptimization::EnableFrameDropper(bool enable) {
   frame_dropper_->Enable(enable);
 }
 
 bool MediaOptimization::DropFrame() {
+  UpdateIncomingFrameRate();
   // Leak appropriate number of bytes.
   frame_dropper_->Leak((uint32_t)(InputFrameRate() + 0.5f));
   if (video_suspended_) {
@@ -356,12 +402,6 @@
   return frame_dropper_->DropFrame();
 }
 
-int32_t MediaOptimization::SentFrameCount(VCMFrameCount* frame_count) const {
-  frame_count->numDeltaFrames = delta_frame_cnt_;
-  frame_count->numKeyFrames = key_frame_cnt_;
-  return VCM_OK;
-}
-
 void MediaOptimization::UpdateIncomingFrameRate() {
   int64_t now = clock_->TimeInMilliseconds();
   if (incoming_frame_times_[0] == 0) {
@@ -388,7 +428,8 @@
   }
 }
 
-int32_t MediaOptimization::SelectQuality() {
+int32_t MediaOptimization::SelectQuality(
+    VCMQMSettingsCallback* video_qmsettings_callback) {
   // Reset quantities for QM select.
   qm_resolution_->ResetQM();
 
@@ -403,7 +444,7 @@
   }
 
   // Check for updates to spatial/temporal modes.
-  QMUpdate(qm);
+  QMUpdate(qm, video_qmsettings_callback);
 
   // Reset all the rate and related frame counters quantities.
   qm_resolution_->ResetRates();
@@ -426,50 +467,7 @@
   video_suspended_ = false;
 }
 
-// Private methods below this line.
-
-int MediaOptimization::UpdateProtectionCallback(
-    VCMProtectionMethod* selected_method,
-    uint32_t* video_rate_bps,
-    uint32_t* nack_overhead_rate_bps,
-    uint32_t* fec_overhead_rate_bps) {
-  if (!video_protection_callback_) {
-    return VCM_OK;
-  }
-  FecProtectionParams delta_fec_params;
-  FecProtectionParams key_fec_params;
-  // Get the FEC code rate for Key frames (set to 0 when NA).
-  key_fec_params.fec_rate = selected_method->RequiredProtectionFactorK();
-
-  // Get the FEC code rate for Delta frames (set to 0 when NA).
-  delta_fec_params.fec_rate = selected_method->RequiredProtectionFactorD();
-
-  // Get the FEC-UEP protection status for Key frames: UEP on/off.
-  key_fec_params.use_uep_protection = selected_method->RequiredUepProtectionK();
-
-  // Get the FEC-UEP protection status for Delta frames: UEP on/off.
-  delta_fec_params.use_uep_protection =
-      selected_method->RequiredUepProtectionD();
-
-  // The RTP module currently requires the same |max_fec_frames| for both
-  // key and delta frames.
-  delta_fec_params.max_fec_frames = selected_method->MaxFramesFec();
-  key_fec_params.max_fec_frames = selected_method->MaxFramesFec();
-
-  // Set the FEC packet mask type. |kFecMaskBursty| is more effective for
-  // consecutive losses and little/no packet re-ordering. As we currently
-  // do not have feedback data on the degree of correlated losses and packet
-  // re-ordering, we keep default setting to |kFecMaskRandom| for now.
-  delta_fec_params.fec_mask_type = kFecMaskRandom;
-  key_fec_params.fec_mask_type = kFecMaskRandom;
-
-  // TODO(Marco): Pass FEC protection values per layer.
-  return video_protection_callback_->ProtectionRequest(&delta_fec_params,
-                                                       &key_fec_params,
-                                                       video_rate_bps,
-                                                       nack_overhead_rate_bps,
-                                                       fec_overhead_rate_bps);
-}
+bool MediaOptimization::IsVideoSuspended() const { return video_suspended_; }
 
 void MediaOptimization::PurgeOldFrameSamples(int64_t now_ms) {
   while (!encoded_frame_samples_.empty()) {
@@ -518,7 +516,9 @@
   }
 }
 
-bool MediaOptimization::QMUpdate(VCMResolutionScale* qm) {
+bool MediaOptimization::QMUpdate(
+    VCMResolutionScale* qm,
+    VCMQMSettingsCallback* video_qmsettings_callback) {
   // Check for no change.
   if (!qm->change_resolution_spatial && !qm->change_resolution_temporal) {
     return false;
@@ -551,7 +551,7 @@
   // will vary/fluctuate, and since we don't want to change the state of the
   // VPM frame dropper, unless a temporal action was selected, we use the
   // quantity |qm->frame_rate| for updating.
-  video_qmsettings_callback_->SetVideoQMSettings(
+  video_qmsettings_callback->SetVideoQMSettings(
       qm->frame_rate, codec_width_, codec_height_);
   content_->UpdateFrameRate(qm->frame_rate);
   qm_resolution_->UpdateCodecParameters(
diff --git a/webrtc/modules/video_coding/main/source/media_optimization.h b/webrtc/modules/video_coding/main/source/media_optimization.h
index cde28d2..3c3c8e4 100644
--- a/webrtc/modules/video_coding/main/source/media_optimization.h
+++ b/webrtc/modules/video_coding/main/source/media_optimization.h
@@ -29,33 +29,25 @@
 
 namespace media_optimization {
 
-enum {
-  kBitrateMaxFrameSamples = 60
-};
-enum {
-  kBitrateAverageWinMs = 1000
-};
-
-struct EncodedFrameSample {
-  EncodedFrameSample(int size_bytes,
-                     uint32_t timestamp,
-                     int64_t time_complete_ms)
-      : size_bytes(size_bytes),
-        timestamp(timestamp),
-        time_complete_ms(time_complete_ms) {}
-
-  uint32_t size_bytes;
-  uint32_t timestamp;
-  int64_t time_complete_ms;
-};
-
+// TODO(andresp): Make thread safe.
 class MediaOptimization {
  public:
   MediaOptimization(int32_t id, Clock* clock);
-  ~MediaOptimization(void);
+  ~MediaOptimization();
 
-  // Resets the Media Optimization module.
-  int32_t Reset();
+  // TODO(andresp): Can Reset and SetEncodingData be done at construction time
+  // only?
+  void Reset();
+
+  // Informs media optimization of initial encoding state.
+  void SetEncodingData(VideoCodecType send_codec_type,
+                       int32_t max_bit_rate,
+                       uint32_t frame_rate,
+                       uint32_t bit_rate,
+                       uint16_t width,
+                       uint16_t height,
+                       int num_temporal_layers,
+                       int32_t mtu);
 
   // Sets target rates for the encoder given the channel parameters.
   // Inputs:  target bitrate - the encoder target bitrate in bits/s.
@@ -63,95 +55,64 @@
   //          round_trip_time_ms - round trip time in milliseconds.
   //          min_bit_rate - the bit rate of the end-point with lowest rate.
   //          max_bit_rate - the bit rate of the end-point with highest rate.
+  // TODO(andresp): Find if the callbacks can be triggered only after releasing
+  // an internal critical section.
   uint32_t SetTargetRates(uint32_t target_bitrate,
                           uint8_t fraction_lost,
-                          uint32_t round_trip_time_ms);
+                          uint32_t round_trip_time_ms,
+                          VCMProtectionCallback* protection_callback,
+                          VCMQMSettingsCallback* qmsettings_callback);
 
-  // Informs media optimization of initial encoding state.
-  int32_t SetEncodingData(VideoCodecType send_codec_type,
-                          int32_t max_bit_rate,
-                          uint32_t frame_rate,
-                          uint32_t bit_rate,
-                          uint16_t width,
-                          uint16_t height,
-                          int num_temporal_layers);
-
-  // Enables protection method.
   void EnableProtectionMethod(bool enable, VCMProtectionMethodEnum method);
+  void EnableQM(bool enable);
+  void EnableFrameDropper(bool enable);
 
-  // Returns weather or not protection method is enabled.
-  bool IsProtectionMethodEnabled(VCMProtectionMethodEnum method);
+  // Lets the sender suspend video when the rate drops below
+  // |threshold_bps|, and turns back on when the rate goes back up above
+  // |threshold_bps| + |window_bps|.
+  void SuspendBelowMinBitrate(int threshold_bps, int window_bps);
+  bool IsVideoSuspended() const;
 
-  // Returns the actual input frame rate.
-  uint32_t InputFrameRate();
+  bool DropFrame();
 
-  // Returns the actual sent frame rate.
-  uint32_t SentFrameRate();
-
-  // Returns the actual sent bit rate.
-  uint32_t SentBitRate();
+  void UpdateContentData(const VideoContentMetrics* content_metrics);
 
   // Informs Media Optimization of encoding output: Length and frame type.
   int32_t UpdateWithEncodedData(int encoded_length,
                                 uint32_t timestamp,
                                 FrameType encoded_frame_type);
 
-  // Registers a protection callback to be used to inform the user about the
-  // protection methods used.
-  int32_t RegisterProtectionCallback(
-      VCMProtectionCallback* protection_callback);
-
-  // Registers a quality settings callback to be used to inform VPM/user.
-  int32_t RegisterVideoQMCallback(VCMQMSettingsCallback* video_qmsettings);
-
-  void EnableFrameDropper(bool enable);
-
-  bool DropFrame();
-
-  // Returns the number of key/delta frames encoded.
-  int32_t SentFrameCount(VCMFrameCount* frame_count) const;
-
-  // Updates incoming frame rate value.
-  void UpdateIncomingFrameRate();
-
-  // Update content metric data.
-  void UpdateContentData(const VideoContentMetrics* content_metrics);
-
-  // Computes new Quality Mode.
-  int32_t SelectQuality();
-
-  // Lets the sender suspend video when the rate drops below
-  // |threshold_bps|, and turns back on when the rate goes back up above
-  // |threshold_bps| + |window_bps|.
-  void SuspendBelowMinBitrate(int threshold_bps, int window_bps);
-
-  // Accessors and mutators.
-  int32_t max_bit_rate() const { return max_bit_rate_; }
-  void set_max_payload_size(int32_t mtu) { max_payload_size_ = mtu; }
-  bool video_suspended() const { return video_suspended_; }
+  uint32_t InputFrameRate();
+  uint32_t SentFrameRate();
+  uint32_t SentBitRate();
+  VCMFrameCount SentFrameCount();
 
  private:
-  typedef std::list<EncodedFrameSample> FrameSampleList;
   enum {
     kFrameCountHistorySize = 90
   };
   enum {
     kFrameHistoryWinMs = 2000
   };
+  enum {
+    kBitrateAverageWinMs = 1000
+  };
 
-  // Updates protection callback with protection settings.
-  int UpdateProtectionCallback(VCMProtectionMethod* selected_method,
-                               uint32_t* total_video_rate_bps,
-                               uint32_t* nack_overhead_rate_bps,
-                               uint32_t* fec_overhead_rate_bps);
+  struct EncodedFrameSample;
+  typedef std::list<EncodedFrameSample> FrameSampleList;
 
+  void UpdateIncomingFrameRate();
   void PurgeOldFrameSamples(int64_t now_ms);
   void UpdateSentBitrate(int64_t now_ms);
   void UpdateSentFramerate();
 
+  // Computes new Quality Mode.
+  int32_t SelectQuality(VCMQMSettingsCallback* qmsettings_callback);
+
   // Verifies if QM settings differ from default, i.e. if an update is required.
   // Computes actual values, as will be sent to the encoder.
-  bool QMUpdate(VCMResolutionScale* qm);
+  bool QMUpdate(VCMResolutionScale* qm,
+                VCMQMSettingsCallback* qmsettings_callback);
 
   // Checks if we should make a QM change. Return true if yes, false otherwise.
   bool CheckStatusForQMchange();
@@ -180,8 +141,6 @@
   float incoming_frame_rate_;
   int64_t incoming_frame_times_[kFrameCountHistorySize];
   bool enable_qm_;
-  VCMProtectionCallback* video_protection_callback_;
-  VCMQMSettingsCallback* video_qmsettings_callback_;
   std::list<EncodedFrameSample> encoded_frame_samples_;
   uint32_t avg_sent_bit_rate_bps_;
   uint32_t avg_sent_framerate_;
@@ -196,8 +155,7 @@
   bool video_suspended_;
   int suspension_threshold_bps_;
   int suspension_window_bps_;
-};  // End of MediaOptimization class declaration.
-
+};
 }  // namespace media_optimization
 }  // namespace webrtc
 
diff --git a/webrtc/modules/video_coding/main/source/media_optimization_unittest.cc b/webrtc/modules/video_coding/main/source/media_optimization_unittest.cc
index 1425dad..d58ada6 100644
--- a/webrtc/modules/video_coding/main/source/media_optimization_unittest.cc
+++ b/webrtc/modules/video_coding/main/source/media_optimization_unittest.cc
@@ -35,7 +35,6 @@
   // This method mimics what happens in VideoSender::AddVideoFrame.
   void AddFrameAndAdvanceTime(int bitrate_bps, bool expect_frame_drop) {
     ASSERT_GE(bitrate_bps, 0);
-    media_opt_.UpdateIncomingFrameRate();
     bool frame_dropped = media_opt_.DropFrame();
     EXPECT_EQ(expect_frame_drop, frame_dropped);
     if (!frame_dropped) {
@@ -63,12 +62,14 @@
   media_opt_.SuspendBelowMinBitrate(kThresholdBps, kWindowBps);
 
   // The video should not be suspended from the start.
-  EXPECT_FALSE(media_opt_.video_suspended());
+  EXPECT_FALSE(media_opt_.IsVideoSuspended());
 
   int target_bitrate_kbps = 100;
   media_opt_.SetTargetRates(target_bitrate_kbps * 1000,
                             0,  // Lossrate.
-                            100);  // RTT in ms.
+                            100,
+                            NULL,
+                            NULL);  // RTT in ms.
   media_opt_.EnableFrameDropper(true);
   for (int time = 0; time < 2000; time += frame_time_ms_) {
     ASSERT_NO_FATAL_FAILURE(AddFrameAndAdvanceTime(target_bitrate_kbps, false));
@@ -77,11 +78,13 @@
   // Set the target rate below the limit for muting.
   media_opt_.SetTargetRates(kThresholdBps - 1000,
                             0,  // Lossrate.
-                            100);  // RTT in ms.
+                            100,
+                            NULL,
+                            NULL);  // RTT in ms.
   // Expect the muter to engage immediately and stay muted.
   // Test during 2 seconds.
   for (int time = 0; time < 2000; time += frame_time_ms_) {
-    EXPECT_TRUE(media_opt_.video_suspended());
+    EXPECT_TRUE(media_opt_.IsVideoSuspended());
     ASSERT_NO_FATAL_FAILURE(AddFrameAndAdvanceTime(target_bitrate_kbps, true));
   }
 
@@ -89,22 +92,26 @@
   // limit + window.
   media_opt_.SetTargetRates(kThresholdBps + 1000,
                             0,  // Lossrate.
-                            100);  // RTT in ms.
-  // Expect the muter to stay muted.
+                            100,
+                            NULL,
+                            NULL);  // RTT in ms.
+                                    // Expect the muter to stay muted.
   // Test during 2 seconds.
   for (int time = 0; time < 2000; time += frame_time_ms_) {
-    EXPECT_TRUE(media_opt_.video_suspended());
+    EXPECT_TRUE(media_opt_.IsVideoSuspended());
     ASSERT_NO_FATAL_FAILURE(AddFrameAndAdvanceTime(target_bitrate_kbps, true));
   }
 
   // Set the target above limit + window.
   media_opt_.SetTargetRates(kThresholdBps + kWindowBps + 1000,
                             0,  // Lossrate.
-                            100);  // RTT in ms.
+                            100,
+                            NULL,
+                            NULL);  // RTT in ms.
   // Expect the muter to disengage immediately.
   // Test during 2 seconds.
   for (int time = 0; time < 2000; time += frame_time_ms_) {
-    EXPECT_FALSE(media_opt_.video_suspended());
+    EXPECT_FALSE(media_opt_.IsVideoSuspended());
     ASSERT_NO_FATAL_FAILURE(
         AddFrameAndAdvanceTime((kThresholdBps + kWindowBps) / 1000, false));
   }
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 d9564c0..5ecb02a 100644
--- a/webrtc/modules/video_coding/main/source/video_coding_impl.h
+++ b/webrtc/modules/video_coding/main/source/video_coding_impl.h
@@ -68,7 +68,8 @@
                                   uint8_t payloadType,
                                   bool internalSource);
 
-  int32_t CodecConfigParameters(uint8_t* buffer, int32_t size);
+  int32_t CodecConfigParameters(uint8_t* buffer, int32_t size) const;
+  int32_t SentFrameCount(VCMFrameCount* frameCount);
   int Bitrate(unsigned int* bitrate) const;
   int FrameRate(unsigned int* framerate) const;
 
@@ -88,7 +89,6 @@
 
   int32_t IntraFrameRequest(int stream_index);
   int32_t EnableFrameDropper(bool enable);
-  int32_t SentFrameCount(VCMFrameCount* frameCount) const;
 
   int SetSenderNackMode(SenderNackMode mode);
   int SetSenderReferenceSelection(bool enable);
@@ -122,6 +122,9 @@
   VCMCodecDataBase _codecDataBase;
   bool frame_dropper_enabled_;
   VCMProcessTimer _sendStatsTimer;
+
+  VCMQMSettingsCallback* qm_settings_callback_;
+  VCMProtectionCallback* protection_callback_;
 };
 
 class VideoReceiver {
diff --git a/webrtc/modules/video_coding/main/source/video_sender.cc b/webrtc/modules/video_coding/main/source/video_sender.cc
index 948218b..d198966 100644
--- a/webrtc/modules/video_coding/main/source/video_sender.cc
+++ b/webrtc/modules/video_coding/main/source/video_sender.cc
@@ -34,7 +34,9 @@
       _encoderInputFile(NULL),
       _codecDataBase(id),
       frame_dropper_enabled_(true),
-      _sendStatsTimer(1000, clock_) {}
+      _sendStatsTimer(1000, clock_),
+      qm_settings_callback_(NULL),
+      protection_callback_(NULL) {}
 
 VideoSender::~VideoSender() {
   delete _sendCritSect;
@@ -70,8 +72,6 @@
   _codecDataBase.ResetSender();
   _encoder = NULL;
   _encodedFrameCallback.SetTransportCallback(NULL);
-  // setting default bitRate and frameRate to 0
-  _mediaOpt.SetEncodingData(kVideoCodecUnknown, 0, 0, 0, 0, 0, 0);
   _mediaOpt.Reset();  // Resetting frame dropper
   return VCM_OK;
 }
@@ -125,9 +125,8 @@
                             sendCodec->startBitrate * 1000,
                             sendCodec->width,
                             sendCodec->height,
-                            numLayers);
-  _mediaOpt.set_max_payload_size(maxPayloadSize);
-
+                            numLayers,
+                            maxPayloadSize);
   return VCM_OK;
 }
 
@@ -171,7 +170,8 @@
 }
 
 // Get codec config parameters
-int32_t VideoSender::CodecConfigParameters(uint8_t* buffer, int32_t size) {
+int32_t VideoSender::CodecConfigParameters(uint8_t* buffer,
+                                           int32_t size) const {
   CriticalSectionScoped cs(_sendCritSect);
   if (_encoder != NULL) {
     return _encoder->CodecConfigParameters(buffer, size);
@@ -179,6 +179,14 @@
   return VCM_UNINITIALIZED;
 }
 
+// TODO(andresp): Make const once media_opt is thread-safe and this has a
+// pointer to it.
+int32_t VideoSender::SentFrameCount(VCMFrameCount* frameCount) {
+  CriticalSectionScoped cs(_sendCritSect);
+  *frameCount = _mediaOpt.SentFrameCount();
+  return VCM_OK;
+}
+
 // Get encode bitrate
 int VideoSender::Bitrate(unsigned int* bitrate) const {
   CriticalSectionScoped cs(_sendCritSect);
@@ -208,8 +216,11 @@
   int32_t ret = 0;
   {
     CriticalSectionScoped sendCs(_sendCritSect);
-    uint32_t targetRate =
-        _mediaOpt.SetTargetRates(target_bitrate, lossRate, rtt);
+    uint32_t targetRate = _mediaOpt.SetTargetRates(target_bitrate,
+                                                   lossRate,
+                                                   rtt,
+                                                   protection_callback_,
+                                                   qm_settings_callback_);
     if (_encoder != NULL) {
       ret = _encoder->SetChannelParameters(lossRate, rtt);
       if (ret < 0) {
@@ -247,17 +258,19 @@
 // Register a video quality settings callback which will be called when frame
 // rate/dimensions need to be updated for video quality optimization
 int32_t VideoSender::RegisterVideoQMCallback(
-    VCMQMSettingsCallback* videoQMSettings) {
+    VCMQMSettingsCallback* qm_settings_callback) {
   CriticalSectionScoped cs(_sendCritSect);
-  return _mediaOpt.RegisterVideoQMCallback(videoQMSettings);
+  qm_settings_callback_ = qm_settings_callback;
+  _mediaOpt.EnableQM(qm_settings_callback_ != NULL);
+  return VCM_OK;
 }
 
 // Register a video protection callback which will be called to deliver the
 // requested FEC rate and NACK status (on/off).
 int32_t VideoSender::RegisterProtectionCallback(
-    VCMProtectionCallback* protection) {
+    VCMProtectionCallback* protection_callback) {
   CriticalSectionScoped cs(_sendCritSect);
-  _mediaOpt.RegisterProtectionCallback(protection);
+  protection_callback_ = protection_callback;
   return VCM_OK;
 }
 
@@ -314,8 +327,6 @@
   if (_nextFrameTypes[0] == kFrameEmpty) {
     return VCM_OK;
   }
-  _mediaOpt.UpdateIncomingFrameRate();
-
   if (_mediaOpt.DropFrame()) {
     WEBRTC_TRACE(webrtc::kTraceStream,
                  webrtc::kTraceVideoCoding,
@@ -369,11 +380,6 @@
   return VCM_OK;
 }
 
-int32_t VideoSender::SentFrameCount(VCMFrameCount* frameCount) const {
-  CriticalSectionScoped cs(_sendCritSect);
-  return _mediaOpt.SentFrameCount(frameCount);
-}
-
 int VideoSender::SetSenderNackMode(SenderNackMode mode) {
   CriticalSectionScoped cs(_sendCritSect);
 
@@ -443,7 +449,7 @@
 
 bool VideoSender::VideoSuspended() const {
   CriticalSectionScoped cs(_sendCritSect);
-  return _mediaOpt.video_suspended();
+  return _mediaOpt.IsVideoSuspended();
 }
 
 void VideoSender::RegisterPostEncodeImageCallback(