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',