Index: webrtc/modules/audio_coding/audio_network_adaptor/controller_manager.cc |
diff --git a/webrtc/modules/audio_coding/audio_network_adaptor/controller_manager.cc b/webrtc/modules/audio_coding/audio_network_adaptor/controller_manager.cc |
index 80079d73b3037809bb8bb4ea8fc057647a043107..9f05b7e7353b6fe16cbfe14592c935fe44c72ca1 100644 |
--- a/webrtc/modules/audio_coding/audio_network_adaptor/controller_manager.cc |
+++ b/webrtc/modules/audio_coding/audio_network_adaptor/controller_manager.cc |
@@ -8,25 +8,46 @@ |
* be found in the AUTHORS file in the root of the source tree. |
*/ |
+#include "webrtc/modules/audio_coding/audio_network_adaptor/controller_manager.h" |
+ |
+#include <cmath> |
#include <utility> |
-#include "webrtc/modules/audio_coding/audio_network_adaptor/controller_manager.h" |
+#include "webrtc/system_wrappers/include/clock.h" |
namespace webrtc { |
-ControllerManagerImpl::Config::Config() = default; |
+ControllerManagerImpl::Config::Config(int min_reordering_time_ms, |
+ float min_reordering_squared_distance, |
+ const Clock* clock) |
+ : min_reordering_time_ms(min_reordering_time_ms), |
+ min_reordering_squared_distance(min_reordering_squared_distance), |
+ clock(clock) {} |
ControllerManagerImpl::Config::~Config() = default; |
ControllerManagerImpl::ControllerManagerImpl(const Config& config) |
- : config_(config) {} |
+ : ControllerManagerImpl( |
+ config, |
+ std::vector<std::unique_ptr<Controller>>(), |
+ std::map<const Controller*, std::pair<int, float>>()) {} |
ControllerManagerImpl::ControllerManagerImpl( |
const Config& config, |
- std::vector<std::unique_ptr<Controller>> controllers) |
- : config_(config), controllers_(std::move(controllers)) { |
- for (auto& controller : controllers_) { |
+ std::vector<std::unique_ptr<Controller>>&& controllers, |
+ const std::map<const Controller*, std::pair<int, float>>& |
+ chracteristic_points) |
+ : config_(config), |
+ controllers_(std::move(controllers)), |
+ last_reordering_time_ms_(rtc::Optional<int64_t>()), |
+ last_scoring_point_(0, 0.0) { |
+ for (auto& controller : controllers_) |
default_sorted_controllers_.push_back(controller.get()); |
+ sorted_controllers_ = default_sorted_controllers_; |
+ for (auto& controller_point : chracteristic_points) { |
+ controller_scoring_points_.insert(std::make_pair( |
+ controller_point.first, ScoringPoint(controller_point.second.first, |
+ controller_point.second.second))); |
} |
} |
@@ -34,12 +55,97 @@ ControllerManagerImpl::~ControllerManagerImpl() = default; |
std::vector<Controller*> ControllerManagerImpl::GetSortedControllers( |
const Controller::NetworkMetrics& metrics) { |
- // TODO(minyue): Reorder controllers according to their significance. |
- return default_sorted_controllers_; |
+ int64_t now_ms = config_.clock->TimeInMilliseconds(); |
+ |
+ if (!metrics.uplink_bandwidth_bps || !metrics.uplink_packet_loss_fraction) |
+ return sorted_controllers_; |
+ |
+ if (last_reordering_time_ms_ && |
+ now_ms - *last_reordering_time_ms_ < config_.min_reordering_time_ms) |
+ return sorted_controllers_; |
+ |
+ ScoringPoint scoring_point(*metrics.uplink_bandwidth_bps, |
+ *metrics.uplink_packet_loss_fraction); |
+ |
+ if (last_reordering_time_ms_ && |
+ last_scoring_point_.SquaredDistanceTo(scoring_point) < |
+ config_.min_reordering_squared_distance) |
+ return sorted_controllers_; |
+ |
+ // Sort controllers according to the distances of |scoring_point| to the |
+ // characteristic scoring points of controllers. |
+ // |
+ // A controller that does not associate with any scoring point |
+ // are treated as if |
+ // 1) they are less important than any controller that has a scoring point, |
+ // 2) they are equally important to any controller that has no scoring point, |
+ // and their relative order will follow |default_sorted_controllers_|. |
+ std::vector<Controller*> sorted_controllers(default_sorted_controllers_); |
+ std::stable_sort( |
+ sorted_controllers.begin(), sorted_controllers.end(), |
+ [this, &scoring_point](const Controller* lhs, const Controller* rhs) { |
+ auto lhs_scoring_point = controller_scoring_points_.find(lhs); |
+ auto rhs_scoring_point = controller_scoring_points_.find(rhs); |
+ |
+ if (lhs_scoring_point == controller_scoring_points_.end()) |
+ return false; |
+ |
+ if (rhs_scoring_point == controller_scoring_points_.end()) |
+ return true; |
+ |
+ return lhs_scoring_point->second.SquaredDistanceTo(scoring_point) < |
+ rhs_scoring_point->second.SquaredDistanceTo(scoring_point); |
+ }); |
+ |
+ if (sorted_controllers_ != sorted_controllers) { |
+ sorted_controllers_ = sorted_controllers; |
+ last_reordering_time_ms_ = rtc::Optional<int64_t>(now_ms); |
+ last_scoring_point_ = scoring_point; |
+ } |
+ return sorted_controllers_; |
} |
std::vector<Controller*> ControllerManagerImpl::GetControllers() const { |
return default_sorted_controllers_; |
} |
+ControllerManagerImpl::ScoringPoint::ScoringPoint( |
+ int uplink_bandwidth_bps, |
+ float uplink_packet_loss_fraction) |
+ : uplink_bandwidth_bps(uplink_bandwidth_bps), |
+ uplink_packet_loss_fraction(uplink_packet_loss_fraction) {} |
+ |
+namespace { |
+ |
+constexpr int kMinUplinkBandwidthBps = 0; |
+constexpr int kMaxUplinkBandwidthBps = 120000; |
+ |
+float NormalizeUplinkBandwidth(int uplink_bandwidth_bps) { |
+ uplink_bandwidth_bps = |
+ std::min(kMaxUplinkBandwidthBps, |
+ std::max(kMinUplinkBandwidthBps, uplink_bandwidth_bps)); |
+ return static_cast<float>(uplink_bandwidth_bps - kMinUplinkBandwidthBps) / |
+ (kMaxUplinkBandwidthBps - kMinUplinkBandwidthBps); |
+} |
+ |
+float NormalizePacketLossFraction(float uplink_packet_loss_fraction) { |
+ // |uplink_packet_loss_fraction| is seldom larger than 0.3, so we scale it up |
+ // by 3.3333f. |
+ return std::min(uplink_packet_loss_fraction * 3.3333f, 1.0f); |
+} |
+ |
+} // namespace |
+ |
+float ControllerManagerImpl::ScoringPoint::SquaredDistanceTo( |
+ const ScoringPoint& scoring_point) const { |
+ float diff_normalized_bitrate_bps = |
+ NormalizeUplinkBandwidth(scoring_point.uplink_bandwidth_bps) - |
+ NormalizeUplinkBandwidth(uplink_bandwidth_bps); |
+ float diff_normalized_packet_loss = |
+ NormalizePacketLossFraction(scoring_point.uplink_packet_loss_fraction) - |
+ NormalizePacketLossFraction(uplink_packet_loss_fraction); |
+ return std::pow(diff_normalized_bitrate_bps, 2) + |
+ std::pow(diff_normalized_packet_loss, 2); |
+} |
+ |
} // namespace webrtc |