Adding API for setting bandwidth estimation configurations.

R=mflodman@webrtc.org

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

git-svn-id: http://webrtc.googlecode.com/svn/trunk@5773 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/webrtc/experiments.h b/webrtc/experiments.h
index 4b5661b..b03d248 100644
--- a/webrtc/experiments.h
+++ b/webrtc/experiments.h
@@ -39,5 +39,14 @@
 
   const bool enabled;
 };
+
+struct AimdRemoteRateControl {
+  AimdRemoteRateControl() : enabled(false) {}
+  explicit AimdRemoteRateControl(bool set_enabled)
+    : enabled(set_enabled) {}
+  virtual ~AimdRemoteRateControl() {}
+
+  const bool enabled;
+};
 }  // namespace webrtc
 #endif  // WEBRTC_EXPERIMENTS_H_
diff --git a/webrtc/video_engine/include/vie_network.h b/webrtc/video_engine/include/vie_network.h
index 0f2a10c..bb36818 100644
--- a/webrtc/video_engine/include/vie_network.h
+++ b/webrtc/video_engine/include/vie_network.h
@@ -86,6 +86,13 @@
     return 0;
   }
 
+  // TODO(holmer): Remove the default implementation when this has been fixed
+  // in fakewebrtcvideoengine.cc.
+  virtual bool SetBandwidthEstimationConfig(int video_channel,
+                                            const webrtc::Config& config) {
+    return false;
+  }
+
  protected:
   ViENetwork() {}
   virtual ~ViENetwork() {}
diff --git a/webrtc/video_engine/vie_channel_group.cc b/webrtc/video_engine/vie_channel_group.cc
index f4055e4..9ce52a2 100644
--- a/webrtc/video_engine/vie_channel_group.cc
+++ b/webrtc/video_engine/vie_channel_group.cc
@@ -17,6 +17,7 @@
 #include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp.h"
 #include "webrtc/modules/utility/interface/process_thread.h"
 #include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
+#include "webrtc/system_wrappers/interface/thread_annotations.h"
 #include "webrtc/system_wrappers/interface/trace.h"
 #include "webrtc/video_engine/call_stats.h"
 #include "webrtc/video_engine/encoder_state_feedback.h"
@@ -40,8 +41,10 @@
         crit_sect_(CriticalSectionWrapper::CreateCriticalSection()),
         engine_id_(engine_id),
         min_bitrate_bps_(config.Get<RemoteBitrateEstimatorMinRate>().min_rate),
-        rbe_(RemoteBitrateEstimatorFactory().Create(observer_, clock_,
-                                                    kMimdControl,
+        rate_control_type_(kMimdControl),
+        rbe_(RemoteBitrateEstimatorFactory().Create(observer_,
+                                                    clock_,
+                                                    rate_control_type_,
                                                     min_bitrate_bps_)),
         using_absolute_send_time_(false),
         packets_since_absolute_send_time_(0) {
@@ -56,7 +59,7 @@
                               int payload_size,
                               const RTPHeader& header) {
     CriticalSectionScoped cs(crit_sect_.get());
-    PickEstimator(header);
+    PickEstimatorFromHeader(header);
     rbe_->IncomingPacket(arrival_time_ms, payload_size, header);
   }
 
@@ -91,19 +94,27 @@
     return rbe_->GetStats(output);
   }
 
+  void SetConfig(const webrtc::Config& config) {
+    CriticalSectionScoped cs(crit_sect_.get());
+    RateControlType new_control_type =
+        config.Get<AimdRemoteRateControl>().enabled ? kAimdControl :
+                                                      kMimdControl;
+    if (new_control_type != rate_control_type_) {
+      rate_control_type_ = new_control_type;
+      PickEstimator();
+    }
+  }
+
  private:
-  // Instantiate RBE for Time Offset or Absolute Send Time extensions.
-  void PickEstimator(const RTPHeader& header) {
+  void PickEstimatorFromHeader(const RTPHeader& header)
+      EXCLUSIVE_LOCKS_REQUIRED(crit_sect_.get()) {
     if (header.extension.hasAbsoluteSendTime) {
       // If we see AST in header, switch RBE strategy immediately.
       if (!using_absolute_send_time_) {
-        process_thread_->DeRegisterModule(rbe_.get());
         WEBRTC_TRACE(kTraceStateInfo, kTraceVideo, ViEId(engine_id_),
             "WrappingBitrateEstimator: Switching to absolute send time RBE.");
-        rbe_.reset(AbsoluteSendTimeRemoteBitrateEstimatorFactory().Create(
-            observer_, clock_, kMimdControl, min_bitrate_bps_));
-        process_thread_->RegisterModule(rbe_.get());
         using_absolute_send_time_ = true;
+        PickEstimator();
       }
       packets_since_absolute_send_time_ = 0;
     } else {
@@ -111,25 +122,36 @@
       if (using_absolute_send_time_) {
         ++packets_since_absolute_send_time_;
         if (packets_since_absolute_send_time_ >= kTimeOffsetSwitchThreshold) {
-          process_thread_->DeRegisterModule(rbe_.get());
           WEBRTC_TRACE(kTraceStateInfo, kTraceVideo, ViEId(engine_id_),
               "WrappingBitrateEstimator: Switching to transmission time offset "
               "RBE.");
-          rbe_.reset(RemoteBitrateEstimatorFactory().Create(observer_, clock_,
-              kMimdControl, min_bitrate_bps_));
-          process_thread_->RegisterModule(rbe_.get());
           using_absolute_send_time_ = false;
+          PickEstimator();
         }
       }
     }
   }
 
+  // Instantiate RBE for Time Offset or Absolute Send Time extensions.
+  void PickEstimator() EXCLUSIVE_LOCKS_REQUIRED(crit_sect_.get()) {
+    process_thread_->DeRegisterModule(rbe_.get());
+    if (using_absolute_send_time_) {
+      rbe_.reset(AbsoluteSendTimeRemoteBitrateEstimatorFactory().Create(
+          observer_, clock_, rate_control_type_, min_bitrate_bps_));
+    } else {
+      rbe_.reset(RemoteBitrateEstimatorFactory().Create(
+          observer_, clock_, rate_control_type_, min_bitrate_bps_));
+    }
+    process_thread_->RegisterModule(rbe_.get());
+  }
+
   RemoteBitrateObserver* observer_;
   Clock* clock_;
   ProcessThread* process_thread_;
   scoped_ptr<CriticalSectionWrapper> crit_sect_;
   const int engine_id_;
   const uint32_t min_bitrate_bps_;
+  RateControlType rate_control_type_;
   scoped_ptr<RemoteBitrateEstimator> rbe_;
   bool using_absolute_send_time_;
   uint32_t packets_since_absolute_send_time_;
@@ -224,4 +246,10 @@
   }
   return true;
 }
+
+void ChannelGroup::SetBandwidthEstimationConfig(const webrtc::Config& config) {
+  WrappingBitrateEstimator* estimator =
+      static_cast<WrappingBitrateEstimator*>(remote_bitrate_estimator_.get());
+  estimator->SetConfig(config);
+}
 }  // namespace webrtc
diff --git a/webrtc/video_engine/vie_channel_group.h b/webrtc/video_engine/vie_channel_group.h
index 036967f..40ce71e 100644
--- a/webrtc/video_engine/vie_channel_group.h
+++ b/webrtc/video_engine/vie_channel_group.h
@@ -42,6 +42,7 @@
 
   bool SetChannelRembStatus(int channel_id, bool sender, bool receiver,
                             ViEChannel* channel);
+  void SetBandwidthEstimationConfig(const webrtc::Config& config);
 
   BitrateController* GetBitrateController();
   CallStats* GetCallStats();
diff --git a/webrtc/video_engine/vie_channel_manager.cc b/webrtc/video_engine/vie_channel_manager.cc
index 37e4692..746cb25 100644
--- a/webrtc/video_engine/vie_channel_manager.cc
+++ b/webrtc/video_engine/vie_channel_manager.cc
@@ -389,6 +389,17 @@
   }
 }
 
+bool ViEChannelManager::SetBandwidthEstimationConfig(
+    int channel_id, const webrtc::Config& config) {
+  CriticalSectionScoped cs(channel_id_critsect_);
+  ChannelGroup* group = FindGroup(channel_id);
+  if (!group) {
+    return false;
+  }
+  group->SetBandwidthEstimationConfig(config);
+  return true;
+}
+
 bool ViEChannelManager::CreateChannelObject(
     int channel_id,
     ViEEncoder* vie_encoder,
diff --git a/webrtc/video_engine/vie_channel_manager.h b/webrtc/video_engine/vie_channel_manager.h
index 8325098..a979ab6 100644
--- a/webrtc/video_engine/vie_channel_manager.h
+++ b/webrtc/video_engine/vie_channel_manager.h
@@ -79,6 +79,10 @@
   // it will simply be ignored and no error is returned.
   void UpdateSsrcs(int channel_id, const std::list<unsigned int>& ssrcs);
 
+  // Sets bandwidth estimation related configurations.
+  bool SetBandwidthEstimationConfig(int channel_id,
+                                    const webrtc::Config& config);
+
  private:
   // Creates a channel object connected to |vie_encoder|. Assumed to be called
   // protected.
diff --git a/webrtc/video_engine/vie_network_impl.cc b/webrtc/video_engine/vie_network_impl.cc
index 8c3e1eb0..2b80159 100644
--- a/webrtc/video_engine/vie_network_impl.cc
+++ b/webrtc/video_engine/vie_network_impl.cc
@@ -217,4 +217,13 @@
   vie_channel->ReceivedBWEPacket(arrival_time_ms, payload_size, header);
   return 0;
 }
+
+bool ViENetworkImpl::SetBandwidthEstimationConfig(
+    int video_channel, const webrtc::Config& config) {
+  WEBRTC_TRACE(kTraceApiCall, kTraceVideo,
+               ViEId(shared_data_->instance_id(), video_channel),
+               "%s(channel: %d)", __FUNCTION__, video_channel);
+  return shared_data_->channel_manager()->SetBandwidthEstimationConfig(
+      video_channel, config);
+}
 }  // namespace webrtc
diff --git a/webrtc/video_engine/vie_network_impl.h b/webrtc/video_engine/vie_network_impl.h
index 26d8a9f..03547d8 100644
--- a/webrtc/video_engine/vie_network_impl.h
+++ b/webrtc/video_engine/vie_network_impl.h
@@ -38,8 +38,13 @@
                                  const void* data,
                                  const int length);
   virtual int SetMTU(int video_channel, unsigned int mtu);
+
   virtual int ReceivedBWEPacket(const int video_channel,
       int64_t arrival_time_ms, int payload_size, const RTPHeader& header);
+
+  virtual bool SetBandwidthEstimationConfig(int video_channel,
+                                            const webrtc::Config& config);
+
  protected:
   explicit ViENetworkImpl(ViESharedData* shared_data);
   virtual ~ViENetworkImpl();