diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
commit | 26a029d407be480d791972afb5975cf62c9360a6 (patch) | |
tree | f435a8308119effd964b339f76abb83a57c29483 /third_party/libwebrtc/modules/audio_coding/audio_network_adaptor/controller_manager.cc | |
parent | Initial commit. (diff) | |
download | firefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz firefox-26a029d407be480d791972afb5975cf62c9360a6.zip |
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/libwebrtc/modules/audio_coding/audio_network_adaptor/controller_manager.cc')
-rw-r--r-- | third_party/libwebrtc/modules/audio_coding/audio_network_adaptor/controller_manager.cc | 454 |
1 files changed, 454 insertions, 0 deletions
diff --git a/third_party/libwebrtc/modules/audio_coding/audio_network_adaptor/controller_manager.cc b/third_party/libwebrtc/modules/audio_coding/audio_network_adaptor/controller_manager.cc new file mode 100644 index 0000000000..42dd8a8786 --- /dev/null +++ b/third_party/libwebrtc/modules/audio_coding/audio_network_adaptor/controller_manager.cc @@ -0,0 +1,454 @@ +/* + * 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 "modules/audio_coding/audio_network_adaptor/controller_manager.h" + +#include <cmath> +#include <memory> +#include <string> +#include <utility> + +#include "absl/strings/string_view.h" +#include "modules/audio_coding/audio_network_adaptor/bitrate_controller.h" +#include "modules/audio_coding/audio_network_adaptor/channel_controller.h" +#include "modules/audio_coding/audio_network_adaptor/debug_dump_writer.h" +#include "modules/audio_coding/audio_network_adaptor/dtx_controller.h" +#include "modules/audio_coding/audio_network_adaptor/fec_controller_plr_based.h" +#include "modules/audio_coding/audio_network_adaptor/frame_length_controller.h" +#include "modules/audio_coding/audio_network_adaptor/frame_length_controller_v2.h" +#include "modules/audio_coding/audio_network_adaptor/util/threshold_curve.h" +#include "rtc_base/ignore_wundef.h" +#include "rtc_base/logging.h" +#include "rtc_base/time_utils.h" + +#if WEBRTC_ENABLE_PROTOBUF +RTC_PUSH_IGNORING_WUNDEF() +#ifdef WEBRTC_ANDROID_PLATFORM_BUILD +#include "external/webrtc/webrtc/modules/audio_coding/audio_network_adaptor/config.pb.h" +#else +#include "modules/audio_coding/audio_network_adaptor/config.pb.h" +#endif +RTC_POP_IGNORING_WUNDEF() +#endif + +namespace webrtc { + +namespace { + +#if WEBRTC_ENABLE_PROTOBUF + +std::unique_ptr<FecControllerPlrBased> CreateFecControllerPlrBased( + const audio_network_adaptor::config::FecController& config, + bool initial_fec_enabled) { + RTC_CHECK(config.has_fec_enabling_threshold()); + RTC_CHECK(config.has_fec_disabling_threshold()); + RTC_CHECK(config.has_time_constant_ms()); + + auto& fec_enabling_threshold = config.fec_enabling_threshold(); + RTC_CHECK(fec_enabling_threshold.has_low_bandwidth_bps()); + RTC_CHECK(fec_enabling_threshold.has_low_bandwidth_packet_loss()); + RTC_CHECK(fec_enabling_threshold.has_high_bandwidth_bps()); + RTC_CHECK(fec_enabling_threshold.has_high_bandwidth_packet_loss()); + + auto& fec_disabling_threshold = config.fec_disabling_threshold(); + RTC_CHECK(fec_disabling_threshold.has_low_bandwidth_bps()); + RTC_CHECK(fec_disabling_threshold.has_low_bandwidth_packet_loss()); + RTC_CHECK(fec_disabling_threshold.has_high_bandwidth_bps()); + RTC_CHECK(fec_disabling_threshold.has_high_bandwidth_packet_loss()); + + return std::unique_ptr<FecControllerPlrBased>( + new FecControllerPlrBased(FecControllerPlrBased::Config( + initial_fec_enabled, + ThresholdCurve(fec_enabling_threshold.low_bandwidth_bps(), + fec_enabling_threshold.low_bandwidth_packet_loss(), + fec_enabling_threshold.high_bandwidth_bps(), + fec_enabling_threshold.high_bandwidth_packet_loss()), + ThresholdCurve(fec_disabling_threshold.low_bandwidth_bps(), + fec_disabling_threshold.low_bandwidth_packet_loss(), + fec_disabling_threshold.high_bandwidth_bps(), + fec_disabling_threshold.high_bandwidth_packet_loss()), + config.time_constant_ms()))); +} + +std::unique_ptr<FrameLengthController> CreateFrameLengthController( + const audio_network_adaptor::config::FrameLengthController& config, + rtc::ArrayView<const int> encoder_frame_lengths_ms, + int initial_frame_length_ms, + int min_encoder_bitrate_bps) { + RTC_CHECK(config.has_fl_increasing_packet_loss_fraction()); + RTC_CHECK(config.has_fl_decreasing_packet_loss_fraction()); + + std::map<FrameLengthController::Config::FrameLengthChange, int> + fl_changing_bandwidths_bps; + + if (config.has_fl_20ms_to_60ms_bandwidth_bps()) { + fl_changing_bandwidths_bps.insert( + std::make_pair(FrameLengthController::Config::FrameLengthChange(20, 60), + config.fl_20ms_to_60ms_bandwidth_bps())); + } + + if (config.has_fl_60ms_to_20ms_bandwidth_bps()) { + fl_changing_bandwidths_bps.insert( + std::make_pair(FrameLengthController::Config::FrameLengthChange(60, 20), + config.fl_60ms_to_20ms_bandwidth_bps())); + } + + if (config.has_fl_20ms_to_40ms_bandwidth_bps()) { + fl_changing_bandwidths_bps.insert( + std::make_pair(FrameLengthController::Config::FrameLengthChange(20, 40), + config.fl_20ms_to_40ms_bandwidth_bps())); + } + + if (config.has_fl_40ms_to_20ms_bandwidth_bps()) { + fl_changing_bandwidths_bps.insert( + std::make_pair(FrameLengthController::Config::FrameLengthChange(40, 20), + config.fl_40ms_to_20ms_bandwidth_bps())); + } + + if (config.has_fl_40ms_to_60ms_bandwidth_bps()) { + fl_changing_bandwidths_bps.insert( + std::make_pair(FrameLengthController::Config::FrameLengthChange(40, 60), + config.fl_40ms_to_60ms_bandwidth_bps())); + } + + if (config.has_fl_60ms_to_40ms_bandwidth_bps()) { + fl_changing_bandwidths_bps.insert( + std::make_pair(FrameLengthController::Config::FrameLengthChange(60, 40), + config.fl_60ms_to_40ms_bandwidth_bps())); + } + + if (config.has_fl_60ms_to_120ms_bandwidth_bps()) { + fl_changing_bandwidths_bps.insert(std::make_pair( + FrameLengthController::Config::FrameLengthChange(60, 120), + config.fl_60ms_to_120ms_bandwidth_bps())); + } + + if (config.has_fl_120ms_to_60ms_bandwidth_bps()) { + fl_changing_bandwidths_bps.insert(std::make_pair( + FrameLengthController::Config::FrameLengthChange(120, 60), + config.fl_120ms_to_60ms_bandwidth_bps())); + } + + int fl_increase_overhead_offset = 0; + if (config.has_fl_increase_overhead_offset()) { + fl_increase_overhead_offset = config.fl_increase_overhead_offset(); + } + int fl_decrease_overhead_offset = 0; + if (config.has_fl_decrease_overhead_offset()) { + fl_decrease_overhead_offset = config.fl_decrease_overhead_offset(); + } + + FrameLengthController::Config ctor_config( + std::set<int>(), initial_frame_length_ms, min_encoder_bitrate_bps, + config.fl_increasing_packet_loss_fraction(), + config.fl_decreasing_packet_loss_fraction(), fl_increase_overhead_offset, + fl_decrease_overhead_offset, std::move(fl_changing_bandwidths_bps)); + + for (auto frame_length : encoder_frame_lengths_ms) + ctor_config.encoder_frame_lengths_ms.insert(frame_length); + + return std::unique_ptr<FrameLengthController>( + new FrameLengthController(ctor_config)); +} + +std::unique_ptr<ChannelController> CreateChannelController( + const audio_network_adaptor::config::ChannelController& config, + size_t num_encoder_channels, + size_t intial_channels_to_encode) { + RTC_CHECK(config.has_channel_1_to_2_bandwidth_bps()); + RTC_CHECK(config.has_channel_2_to_1_bandwidth_bps()); + + return std::unique_ptr<ChannelController>(new ChannelController( + ChannelController::Config(num_encoder_channels, intial_channels_to_encode, + config.channel_1_to_2_bandwidth_bps(), + config.channel_2_to_1_bandwidth_bps()))); +} + +std::unique_ptr<DtxController> CreateDtxController( + const audio_network_adaptor::config::DtxController& dtx_config, + bool initial_dtx_enabled) { + RTC_CHECK(dtx_config.has_dtx_enabling_bandwidth_bps()); + RTC_CHECK(dtx_config.has_dtx_disabling_bandwidth_bps()); + + return std::unique_ptr<DtxController>(new DtxController(DtxController::Config( + initial_dtx_enabled, dtx_config.dtx_enabling_bandwidth_bps(), + dtx_config.dtx_disabling_bandwidth_bps()))); +} + +using audio_network_adaptor::BitrateController; +std::unique_ptr<BitrateController> CreateBitrateController( + const audio_network_adaptor::config::BitrateController& bitrate_config, + int initial_bitrate_bps, + int initial_frame_length_ms) { + int fl_increase_overhead_offset = 0; + if (bitrate_config.has_fl_increase_overhead_offset()) { + fl_increase_overhead_offset = bitrate_config.fl_increase_overhead_offset(); + } + int fl_decrease_overhead_offset = 0; + if (bitrate_config.has_fl_decrease_overhead_offset()) { + fl_decrease_overhead_offset = bitrate_config.fl_decrease_overhead_offset(); + } + return std::unique_ptr<BitrateController>( + new BitrateController(BitrateController::Config( + initial_bitrate_bps, initial_frame_length_ms, + fl_increase_overhead_offset, fl_decrease_overhead_offset))); +} + +std::unique_ptr<FrameLengthControllerV2> CreateFrameLengthControllerV2( + const audio_network_adaptor::config::FrameLengthControllerV2& config, + rtc::ArrayView<const int> encoder_frame_lengths_ms) { + return std::make_unique<FrameLengthControllerV2>( + encoder_frame_lengths_ms, config.min_payload_bitrate_bps(), + config.use_slow_adaptation()); +} +#endif // WEBRTC_ENABLE_PROTOBUF + +} // namespace + +ControllerManagerImpl::Config::Config(int min_reordering_time_ms, + float min_reordering_squared_distance) + : min_reordering_time_ms(min_reordering_time_ms), + min_reordering_squared_distance(min_reordering_squared_distance) {} + +ControllerManagerImpl::Config::~Config() = default; + +std::unique_ptr<ControllerManager> ControllerManagerImpl::Create( + absl::string_view config_string, + size_t num_encoder_channels, + rtc::ArrayView<const int> encoder_frame_lengths_ms, + int min_encoder_bitrate_bps, + size_t intial_channels_to_encode, + int initial_frame_length_ms, + int initial_bitrate_bps, + bool initial_fec_enabled, + bool initial_dtx_enabled) { + return Create(config_string, num_encoder_channels, encoder_frame_lengths_ms, + min_encoder_bitrate_bps, intial_channels_to_encode, + initial_frame_length_ms, initial_bitrate_bps, + initial_fec_enabled, initial_dtx_enabled, nullptr); +} + +std::unique_ptr<ControllerManager> ControllerManagerImpl::Create( + absl::string_view config_string, + size_t num_encoder_channels, + rtc::ArrayView<const int> encoder_frame_lengths_ms, + int min_encoder_bitrate_bps, + size_t intial_channels_to_encode, + int initial_frame_length_ms, + int initial_bitrate_bps, + bool initial_fec_enabled, + bool initial_dtx_enabled, + DebugDumpWriter* debug_dump_writer) { +#if WEBRTC_ENABLE_PROTOBUF + audio_network_adaptor::config::ControllerManager controller_manager_config; + RTC_CHECK( + controller_manager_config.ParseFromString(std::string(config_string))); + if (debug_dump_writer) + debug_dump_writer->DumpControllerManagerConfig(controller_manager_config, + rtc::TimeMillis()); + + std::vector<std::unique_ptr<Controller>> controllers; + std::map<const Controller*, std::pair<int, float>> scoring_points; + + for (int i = 0; i < controller_manager_config.controllers_size(); ++i) { + auto& controller_config = controller_manager_config.controllers(i); + std::unique_ptr<Controller> controller; + switch (controller_config.controller_case()) { + case audio_network_adaptor::config::Controller::kFecController: + controller = CreateFecControllerPlrBased( + controller_config.fec_controller(), initial_fec_enabled); + break; + case audio_network_adaptor::config::Controller::kFecControllerRplrBased: + // FecControllerRplrBased has been removed and can't be used anymore. + RTC_DCHECK_NOTREACHED(); + continue; + case audio_network_adaptor::config::Controller::kFrameLengthController: + controller = CreateFrameLengthController( + controller_config.frame_length_controller(), + encoder_frame_lengths_ms, initial_frame_length_ms, + min_encoder_bitrate_bps); + break; + case audio_network_adaptor::config::Controller::kChannelController: + controller = CreateChannelController( + controller_config.channel_controller(), num_encoder_channels, + intial_channels_to_encode); + break; + case audio_network_adaptor::config::Controller::kDtxController: + controller = CreateDtxController(controller_config.dtx_controller(), + initial_dtx_enabled); + break; + case audio_network_adaptor::config::Controller::kBitrateController: + controller = CreateBitrateController( + controller_config.bitrate_controller(), initial_bitrate_bps, + initial_frame_length_ms); + break; + case audio_network_adaptor::config::Controller::kFrameLengthControllerV2: + controller = CreateFrameLengthControllerV2( + controller_config.frame_length_controller_v2(), + encoder_frame_lengths_ms); + break; + default: + RTC_DCHECK_NOTREACHED(); + } + if (controller_config.has_scoring_point()) { + auto& scoring_point = controller_config.scoring_point(); + RTC_CHECK(scoring_point.has_uplink_bandwidth_bps()); + RTC_CHECK(scoring_point.has_uplink_packet_loss_fraction()); + scoring_points[controller.get()] = std::make_pair<int, float>( + scoring_point.uplink_bandwidth_bps(), + scoring_point.uplink_packet_loss_fraction()); + } + controllers.push_back(std::move(controller)); + } + + if (scoring_points.size() == 0) { + return std::unique_ptr<ControllerManagerImpl>( + new ControllerManagerImpl(ControllerManagerImpl::Config(0, 0), + std::move(controllers), scoring_points)); + } else { + RTC_CHECK(controller_manager_config.has_min_reordering_time_ms()); + RTC_CHECK(controller_manager_config.has_min_reordering_squared_distance()); + return std::unique_ptr<ControllerManagerImpl>(new ControllerManagerImpl( + ControllerManagerImpl::Config( + controller_manager_config.min_reordering_time_ms(), + controller_manager_config.min_reordering_squared_distance()), + std::move(controllers), scoring_points)); + } + +#else + RTC_DCHECK_NOTREACHED(); + return nullptr; +#endif // WEBRTC_ENABLE_PROTOBUF +} + +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>>& scoring_points) + : config_(config), + controllers_(std::move(controllers)), + last_reordering_time_ms_(absl::nullopt), + 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 : scoring_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) { + if (controller_scoring_points_.size() == 0) + return default_sorted_controllers_; + + if (!metrics.uplink_bandwidth_bps || !metrics.uplink_packet_loss_fraction) + return sorted_controllers_; + + const int64_t now_ms = rtc::TimeMillis(); + 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 + // 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_ = 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 |