blob: 9f05b7e7353b6fe16cbfe14592c935fe44c72ca1 [file] [log] [blame]
/*
* 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.
*/
#include "webrtc/modules/audio_coding/audio_network_adaptor/controller_manager.h"
#include <cmath>
#include <utility>
#include "webrtc/system_wrappers/include/clock.h"
namespace webrtc {
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)
: 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,
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)));
}
}
ControllerManagerImpl::~ControllerManagerImpl() = default;
std::vector<Controller*> ControllerManagerImpl::GetSortedControllers(
const Controller::NetworkMetrics& metrics) {
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