Move congestion controller to a separate module.

This allows other projects to more easily depend on this.

The plan is to move remote_bitrate_estimator and bitrate_controller into this module and reduce the exposed interface to only a simplified version of congestion_controller.h.

No functional changes in this CL.

R=mflodman@webrtc.org, pbos@webrtc.org

Review URL: https://codereview.webrtc.org/1718473002 .

Cr-Commit-Position: refs/heads/master@{#11718}
diff --git a/webrtc/modules/congestion_controller/BUILD.gn b/webrtc/modules/congestion_controller/BUILD.gn
new file mode 100644
index 0000000..8723fe4
--- /dev/null
+++ b/webrtc/modules/congestion_controller/BUILD.gn
@@ -0,0 +1,38 @@
+# Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
+#
+# Use of this source code is governed by a BSD-style license
+# that can be found in the LICENSE file in the root of the source
+# tree. An additional intellectual property rights grant can be found
+# in the file PATENTS.  All contributing project authors may
+# be found in the AUTHORS file in the root of the source tree.
+
+import("../../build/webrtc.gni")
+
+source_set("congestion_controller") {
+  sources = [
+    "congestion_controller.cc",
+    "include/congestion_controller.h",
+  ]
+
+  if (is_win) {
+    cflags = [
+      # TODO(jschuh): Bug 1348: fix this warning.
+      "/wd4267",  # size_t to int truncations
+    ]
+  }
+
+  configs += [ "../..:common_config" ]
+  public_configs = [ "../..:common_inherited_config" ]
+
+  if (is_clang) {
+    # Suppress warnings from Chrome's Clang plugins.
+    # See http://code.google.com/p/webrtc/issues/detail?id=163 for details.
+    configs -= [ "//build/config/clang:find_bad_constructs" ]
+  }
+
+  deps = [
+    "../bitrate_controller",
+    "../pacing",
+    "../remote_bitrate_estimator",
+  ]
+}
diff --git a/webrtc/modules/congestion_controller/congestion_controller.cc b/webrtc/modules/congestion_controller/congestion_controller.cc
new file mode 100644
index 0000000..0282e81
--- /dev/null
+++ b/webrtc/modules/congestion_controller/congestion_controller.cc
@@ -0,0 +1,257 @@
+/*
+ *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "webrtc/modules/congestion_controller/include/congestion_controller.h"
+
+#include <algorithm>
+#include <vector>
+
+#include "webrtc/base/checks.h"
+#include "webrtc/base/logging.h"
+#include "webrtc/base/socket.h"
+#include "webrtc/base/thread_annotations.h"
+#include "webrtc/modules/bitrate_controller/include/bitrate_controller.h"
+#include "webrtc/modules/pacing/paced_sender.h"
+#include "webrtc/modules/remote_bitrate_estimator/include/send_time_history.h"
+#include "webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator_abs_send_time.h"
+#include "webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator_single_stream.h"
+#include "webrtc/modules/utility/include/process_thread.h"
+#include "webrtc/system_wrappers/include/critical_section_wrapper.h"
+#include "webrtc/video/payload_router.h"
+
+namespace webrtc {
+namespace {
+
+static const uint32_t kTimeOffsetSwitchThreshold = 30;
+
+class WrappingBitrateEstimator : public RemoteBitrateEstimator {
+ public:
+  WrappingBitrateEstimator(RemoteBitrateObserver* observer, Clock* clock)
+      : observer_(observer),
+        clock_(clock),
+        crit_sect_(CriticalSectionWrapper::CreateCriticalSection()),
+        rbe_(new RemoteBitrateEstimatorSingleStream(observer_, clock_)),
+        using_absolute_send_time_(false),
+        packets_since_absolute_send_time_(0),
+        min_bitrate_bps_(RemoteBitrateEstimator::kDefaultMinBitrateBps) {}
+
+  virtual ~WrappingBitrateEstimator() {}
+
+  void IncomingPacket(int64_t arrival_time_ms,
+                      size_t payload_size,
+                      const RTPHeader& header,
+                      bool was_paced) override {
+    CriticalSectionScoped cs(crit_sect_.get());
+    PickEstimatorFromHeader(header);
+    rbe_->IncomingPacket(arrival_time_ms, payload_size, header, was_paced);
+  }
+
+  int32_t Process() override {
+    CriticalSectionScoped cs(crit_sect_.get());
+    return rbe_->Process();
+  }
+
+  int64_t TimeUntilNextProcess() override {
+    CriticalSectionScoped cs(crit_sect_.get());
+    return rbe_->TimeUntilNextProcess();
+  }
+
+  void OnRttUpdate(int64_t avg_rtt_ms, int64_t max_rtt_ms) override {
+    CriticalSectionScoped cs(crit_sect_.get());
+    rbe_->OnRttUpdate(avg_rtt_ms, max_rtt_ms);
+  }
+
+  void RemoveStream(unsigned int ssrc) override {
+    CriticalSectionScoped cs(crit_sect_.get());
+    rbe_->RemoveStream(ssrc);
+  }
+
+  bool LatestEstimate(std::vector<unsigned int>* ssrcs,
+                      unsigned int* bitrate_bps) const override {
+    CriticalSectionScoped cs(crit_sect_.get());
+    return rbe_->LatestEstimate(ssrcs, bitrate_bps);
+  }
+
+  void SetMinBitrate(int min_bitrate_bps) {
+    CriticalSectionScoped cs(crit_sect_.get());
+    rbe_->SetMinBitrate(min_bitrate_bps);
+    min_bitrate_bps_ = min_bitrate_bps;
+  }
+
+ private:
+  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_) {
+        LOG(LS_INFO) <<
+            "WrappingBitrateEstimator: Switching to absolute send time RBE.";
+        using_absolute_send_time_ = true;
+        PickEstimator();
+      }
+      packets_since_absolute_send_time_ = 0;
+    } else {
+      // When we don't see AST, wait for a few packets before going back to TOF.
+      if (using_absolute_send_time_) {
+        ++packets_since_absolute_send_time_;
+        if (packets_since_absolute_send_time_ >= kTimeOffsetSwitchThreshold) {
+          LOG(LS_INFO) << "WrappingBitrateEstimator: Switching to transmission "
+                       << "time offset RBE.";
+          using_absolute_send_time_ = false;
+          PickEstimator();
+        }
+      }
+    }
+  }
+
+  // Instantiate RBE for Time Offset or Absolute Send Time extensions.
+  void PickEstimator() EXCLUSIVE_LOCKS_REQUIRED(crit_sect_.get()) {
+    if (using_absolute_send_time_) {
+      rbe_.reset(new RemoteBitrateEstimatorAbsSendTime(observer_, clock_));
+    } else {
+      rbe_.reset(new RemoteBitrateEstimatorSingleStream(observer_, clock_));
+    }
+    rbe_->SetMinBitrate(min_bitrate_bps_);
+  }
+
+  RemoteBitrateObserver* observer_;
+  Clock* const clock_;
+  rtc::scoped_ptr<CriticalSectionWrapper> crit_sect_;
+  rtc::scoped_ptr<RemoteBitrateEstimator> rbe_;
+  bool using_absolute_send_time_;
+  uint32_t packets_since_absolute_send_time_;
+  int min_bitrate_bps_;
+
+  RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(WrappingBitrateEstimator);
+};
+
+}  // namespace
+
+CongestionController::CongestionController(
+    Clock* clock,
+    BitrateObserver* bitrate_observer,
+    RemoteBitrateObserver* remote_bitrate_observer)
+    : clock_(clock),
+      pacer_(new PacedSender(clock_,
+             &packet_router_,
+             BitrateController::kDefaultStartBitrateKbps,
+             PacedSender::kDefaultPaceMultiplier *
+                 BitrateController::kDefaultStartBitrateKbps,
+             0)),
+      remote_bitrate_estimator_(
+          new WrappingBitrateEstimator(remote_bitrate_observer, clock_)),
+      pacer_thread_(ProcessThread::Create("PacerThread")),
+      // Constructed last as this object calls the provided callback on
+      // construction.
+      bitrate_controller_(
+          BitrateController::CreateBitrateController(clock_, bitrate_observer)),
+      remote_estimator_proxy_(clock_, &packet_router_),
+      transport_feedback_adapter_(bitrate_controller_.get(), clock_),
+      min_bitrate_bps_(RemoteBitrateEstimator::kDefaultMinBitrateBps) {
+  transport_feedback_adapter_.SetBitrateEstimator(
+      new RemoteBitrateEstimatorAbsSendTime(&transport_feedback_adapter_,
+                                            clock_));
+  transport_feedback_adapter_.GetBitrateEstimator()->SetMinBitrate(
+      min_bitrate_bps_);
+  pacer_thread_->RegisterModule(pacer_.get());
+  pacer_thread_->RegisterModule(&remote_estimator_proxy_);
+  pacer_thread_->Start();
+}
+
+CongestionController::~CongestionController() {
+  pacer_thread_->Stop();
+  pacer_thread_->DeRegisterModule(pacer_.get());
+  pacer_thread_->DeRegisterModule(&remote_estimator_proxy_);
+}
+
+
+void CongestionController::SetBweBitrates(int min_bitrate_bps,
+                                          int start_bitrate_bps,
+                                          int max_bitrate_bps) {
+  RTC_DCHECK(config_thread_checker_.CalledOnValidThread());
+  // TODO(holmer): We should make sure the default bitrates are set to 10 kbps,
+  // and that we don't try to set the min bitrate to 0 from any applications.
+  // The congestion controller should allow a min bitrate of 0.
+  const int kMinBitrateBps = 10000;
+  if (min_bitrate_bps < kMinBitrateBps)
+    min_bitrate_bps = kMinBitrateBps;
+  if (max_bitrate_bps > 0)
+    max_bitrate_bps = std::max(min_bitrate_bps, max_bitrate_bps);
+  if (start_bitrate_bps > 0) {
+    start_bitrate_bps = std::max(min_bitrate_bps, start_bitrate_bps);
+    bitrate_controller_->SetStartBitrate(start_bitrate_bps);
+  }
+  bitrate_controller_->SetMinMaxBitrate(min_bitrate_bps, max_bitrate_bps);
+  if (remote_bitrate_estimator_)
+    remote_bitrate_estimator_->SetMinBitrate(min_bitrate_bps);
+  min_bitrate_bps_ = min_bitrate_bps;
+  transport_feedback_adapter_.GetBitrateEstimator()->SetMinBitrate(
+      min_bitrate_bps_);
+}
+
+BitrateController* CongestionController::GetBitrateController() const {
+  return bitrate_controller_.get();
+}
+
+RemoteBitrateEstimator* CongestionController::GetRemoteBitrateEstimator(
+    bool send_side_bwe) {
+  if (send_side_bwe) {
+    return &remote_estimator_proxy_;
+  } else {
+    return remote_bitrate_estimator_.get();
+  }
+}
+
+TransportFeedbackObserver*
+CongestionController::GetTransportFeedbackObserver() {
+  RTC_DCHECK(config_thread_checker_.CalledOnValidThread());
+  return &transport_feedback_adapter_;
+}
+
+void CongestionController::UpdatePacerBitrate(int bitrate_kbps,
+                                              int max_bitrate_kbps,
+                                              int min_bitrate_kbps) {
+  pacer_->UpdateBitrate(bitrate_kbps, max_bitrate_kbps, min_bitrate_kbps);
+}
+
+int64_t CongestionController::GetPacerQueuingDelayMs() const {
+  return pacer_->QueueInMs();
+}
+
+void CongestionController::SignalNetworkState(NetworkState state) {
+  if (state == kNetworkUp) {
+    pacer_->Resume();
+  } else {
+    pacer_->Pause();
+  }
+}
+
+void CongestionController::OnSentPacket(const rtc::SentPacket& sent_packet) {
+  transport_feedback_adapter_.OnSentPacket(sent_packet.packet_id,
+                                            sent_packet.send_time_ms);
+}
+
+void CongestionController::OnRttUpdate(int64_t avg_rtt_ms, int64_t max_rtt_ms) {
+  remote_bitrate_estimator_->OnRttUpdate(avg_rtt_ms, max_rtt_ms);
+  transport_feedback_adapter_.OnRttUpdate(avg_rtt_ms, max_rtt_ms);
+}
+
+int64_t CongestionController::TimeUntilNextProcess() {
+  return std::min(bitrate_controller_->TimeUntilNextProcess(),
+                  remote_bitrate_estimator_->TimeUntilNextProcess());
+}
+
+int32_t CongestionController::Process() {
+  bitrate_controller_->Process();
+  remote_bitrate_estimator_->Process();
+  return 0;
+}
+
+}  // namespace webrtc
diff --git a/webrtc/modules/congestion_controller/congestion_controller.gypi b/webrtc/modules/congestion_controller/congestion_controller.gypi
new file mode 100644
index 0000000..c2531ab
--- /dev/null
+++ b/webrtc/modules/congestion_controller/congestion_controller.gypi
@@ -0,0 +1,27 @@
+# Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
+#
+# Use of this source code is governed by a BSD-style license
+# that can be found in the LICENSE file in the root of the source
+# tree. An additional intellectual property rights grant can be found
+# in the file PATENTS.  All contributing project authors may
+# be found in the AUTHORS file in the root of the source tree.
+
+{
+  'targets': [
+    {
+      'target_name': 'congestion_controller',
+      'type': 'static_library',
+      'dependencies': [
+        '<(webrtc_root)/modules/modules.gyp:bitrate_controller',
+        '<(webrtc_root)/modules/modules.gyp:paced_sender',
+        '<(webrtc_root)/modules/modules.gyp:remote_bitrate_estimator',
+      ],
+      'sources': [
+        'congestion_controller.cc',
+        'include/congestion_controller.h',
+      ],
+      # TODO(jschuh): Bug 1348: fix size_t to int truncations.
+      'msvs_disabled_warnings': [ 4267, ],
+    },
+  ], # targets
+}
diff --git a/webrtc/modules/congestion_controller/include/congestion_controller.h b/webrtc/modules/congestion_controller/include/congestion_controller.h
new file mode 100644
index 0000000..8c8972d
--- /dev/null
+++ b/webrtc/modules/congestion_controller/include/congestion_controller.h
@@ -0,0 +1,87 @@
+/*
+ *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef WEBRTC_MODULES_CONGESTION_CONTROLLER_INCLUDE_CONGESTION_CONTROLLER_H_
+#define WEBRTC_MODULES_CONGESTION_CONTROLLER_INCLUDE_CONGESTION_CONTROLLER_H_
+
+#include "webrtc/base/scoped_ptr.h"
+#include "webrtc/base/thread_checker.h"
+#include "webrtc/modules/include/module.h"
+#include "webrtc/modules/include/module_common_types.h"
+#include "webrtc/modules/pacing/packet_router.h"
+#include "webrtc/modules/remote_bitrate_estimator/remote_estimator_proxy.h"
+#include "webrtc/modules/remote_bitrate_estimator/transport_feedback_adapter.h"
+#include "webrtc/stream.h"
+
+namespace rtc {
+struct SentPacket;
+}
+
+namespace webrtc {
+
+class BitrateController;
+class BitrateObserver;
+class Clock;
+class PacedSender;
+class ProcessThread;
+class RemoteBitrateEstimator;
+class RemoteBitrateObserver;
+class TransportFeedbackObserver;
+
+class CongestionController : public CallStatsObserver, public Module {
+ public:
+  CongestionController(Clock* clock,
+                       BitrateObserver* bitrate_observer,
+                       RemoteBitrateObserver* remote_bitrate_observer);
+  virtual ~CongestionController();
+
+  virtual void SetBweBitrates(int min_bitrate_bps,
+                              int start_bitrate_bps,
+                              int max_bitrate_bps);
+  virtual void SignalNetworkState(NetworkState state);
+  virtual BitrateController* GetBitrateController() const;
+  virtual RemoteBitrateEstimator* GetRemoteBitrateEstimator(
+      bool send_side_bwe);
+  virtual int64_t GetPacerQueuingDelayMs() const;
+  virtual PacedSender* pacer() { return pacer_.get(); }
+  virtual PacketRouter* packet_router() { return &packet_router_; }
+  virtual TransportFeedbackObserver* GetTransportFeedbackObserver();
+
+  virtual void UpdatePacerBitrate(int bitrate_kbps,
+                                  int max_bitrate_kbps,
+                                  int min_bitrate_kbps);
+
+  virtual void OnSentPacket(const rtc::SentPacket& sent_packet);
+
+  // Implements CallStatsObserver.
+  void OnRttUpdate(int64_t avg_rtt_ms, int64_t max_rtt_ms) override;
+
+  // Implements Module.
+  int64_t TimeUntilNextProcess() override;
+  int32_t Process() override;
+
+ private:
+  Clock* const clock_;
+  rtc::ThreadChecker config_thread_checker_;
+  const rtc::scoped_ptr<PacedSender> pacer_;
+  const rtc::scoped_ptr<RemoteBitrateEstimator> remote_bitrate_estimator_;
+  const rtc::scoped_ptr<ProcessThread> pacer_thread_;
+  const rtc::scoped_ptr<BitrateController> bitrate_controller_;
+  PacketRouter packet_router_;
+  RemoteEstimatorProxy remote_estimator_proxy_;
+  TransportFeedbackAdapter transport_feedback_adapter_;
+  int min_bitrate_bps_;
+
+  RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(CongestionController);
+};
+
+}  // namespace webrtc
+
+#endif  // WEBRTC_MODULES_CONGESTION_CONTROLLER_INCLUDE_CONGESTION_CONTROLLER_H_
diff --git a/webrtc/modules/congestion_controller/include/mock/mock_congestion_controller.h b/webrtc/modules/congestion_controller/include/mock/mock_congestion_controller.h
new file mode 100644
index 0000000..0813c3d
--- /dev/null
+++ b/webrtc/modules/congestion_controller/include/mock/mock_congestion_controller.h
@@ -0,0 +1,51 @@
+/*
+ *  Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef WEBRTC_MODULES_CONGESTION_CONTROLLER_INCLUDE_MOCK_MOCK_CONGESTION_CONTROLLER_H_
+#define WEBRTC_MODULES_CONGESTION_CONTROLLER_INCLUDE_MOCK_MOCK_CONGESTION_CONTROLLER_H_
+
+#include "testing/gmock/include/gmock/gmock.h"
+#include "webrtc/base/socket.h"
+#include "webrtc/modules/congestion_controller/include/congestion_controller.h"
+
+namespace webrtc {
+namespace test {
+
+class MockCongestionController : public CongestionController {
+ public:
+  MockCongestionController(Clock* clock,
+                           BitrateObserver* bitrate_observer,
+                           RemoteBitrateObserver* remote_bitrate_observer)
+      : CongestionController(clock,
+                             bitrate_observer,
+                             remote_bitrate_observer) {}
+  MOCK_METHOD3(SetBweBitrates,
+               void(int min_bitrate_bps,
+                    int start_bitrate_bps,
+                    int max_bitrate_bps));
+  MOCK_METHOD1(SignalNetworkState, void(NetworkState state));
+  MOCK_CONST_METHOD0(GetBitrateController, BitrateController*());
+  MOCK_METHOD1(GetRemoteBitrateEstimator,
+                     RemoteBitrateEstimator*(bool send_side_bwe));
+  MOCK_CONST_METHOD0(GetPacerQueuingDelayMs, int64_t());
+  MOCK_METHOD0(pacer, PacedSender*());
+  MOCK_METHOD0(packet_router, PacketRouter*());
+  MOCK_METHOD0(GetTransportFeedbackObserver, TransportFeedbackObserver*());
+  MOCK_METHOD3(UpdatePacerBitrate,
+               void(int bitrate_kbps,
+                    int max_bitrate_kbps,
+                    int min_bitrate_kbps));
+  MOCK_METHOD1(OnSentPacket, void(const rtc::SentPacket& sent_packet));
+
+  RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(MockCongestionController);
+};
+}  // namespace test
+}  // namespace webrtc
+#endif  // WEBRTC_MODULES_CONGESTION_CONTROLLER_INCLUDE_MOCK_MOCK_CONGESTION_CONTROLLER_H_
diff --git a/webrtc/modules/modules.gyp b/webrtc/modules/modules.gyp
index 683b355..d520156 100644
--- a/webrtc/modules/modules.gyp
+++ b/webrtc/modules/modules.gyp
@@ -14,6 +14,7 @@
     'audio_device/audio_device.gypi',
     'audio_processing/audio_processing.gypi',
     'bitrate_controller/bitrate_controller.gypi',
+    'congestion_controller/congestion_controller.gypi',
     'desktop_capture/desktop_capture.gypi',
     'media_file/media_file.gypi',
     'pacing/pacing.gypi',