/* * 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/bitrate_controller.h" #include "rtc_base/numerics/safe_conversions.h" #include "test/field_trial.h" #include "test/gtest.h" namespace webrtc { namespace audio_network_adaptor { namespace { void UpdateNetworkMetrics( BitrateController* controller, const absl::optional& target_audio_bitrate_bps, const absl::optional& overhead_bytes_per_packet) { // UpdateNetworkMetrics can accept multiple network metric updates at once. // However, currently, the most used case is to update one metric at a time. // To reflect this fact, we separate the calls. if (target_audio_bitrate_bps) { Controller::NetworkMetrics network_metrics; network_metrics.target_audio_bitrate_bps = target_audio_bitrate_bps; controller->UpdateNetworkMetrics(network_metrics); } if (overhead_bytes_per_packet) { Controller::NetworkMetrics network_metrics; network_metrics.overhead_bytes_per_packet = overhead_bytes_per_packet; controller->UpdateNetworkMetrics(network_metrics); } } void CheckDecision(BitrateController* controller, const absl::optional& frame_length_ms, int expected_bitrate_bps) { AudioEncoderRuntimeConfig config; config.frame_length_ms = frame_length_ms; controller->MakeDecision(&config); EXPECT_EQ(expected_bitrate_bps, config.bitrate_bps); } } // namespace // These tests are named AnaBitrateControllerTest to distinguish from // BitrateControllerTest in // modules/bitrate_controller/bitrate_controller_unittest.cc. TEST(AnaBitrateControllerTest, OutputInitValueWhenTargetBitrateUnknown) { constexpr int kInitialBitrateBps = 32000; constexpr int kInitialFrameLengthMs = 20; constexpr size_t kOverheadBytesPerPacket = 64; BitrateController controller(BitrateController::Config( kInitialBitrateBps, kInitialFrameLengthMs, 0, 0)); UpdateNetworkMetrics(&controller, absl::nullopt, kOverheadBytesPerPacket); CheckDecision(&controller, kInitialFrameLengthMs * 2, kInitialBitrateBps); } TEST(AnaBitrateControllerTest, OutputInitValueWhenOverheadUnknown) { constexpr int kInitialBitrateBps = 32000; constexpr int kInitialFrameLengthMs = 20; constexpr int kTargetBitrateBps = 48000; BitrateController controller(BitrateController::Config( kInitialBitrateBps, kInitialFrameLengthMs, 0, 0)); UpdateNetworkMetrics(&controller, kTargetBitrateBps, absl::nullopt); CheckDecision(&controller, kInitialFrameLengthMs * 2, kInitialBitrateBps); } TEST(AnaBitrateControllerTest, ChangeBitrateOnTargetBitrateChanged) { constexpr int kInitialFrameLengthMs = 20; BitrateController controller( BitrateController::Config(32000, kInitialFrameLengthMs, 0, 0)); constexpr int kTargetBitrateBps = 48000; constexpr size_t kOverheadBytesPerPacket = 64; constexpr int kBitrateBps = kTargetBitrateBps - kOverheadBytesPerPacket * 8 * 1000 / kInitialFrameLengthMs; // Frame length unchanged, bitrate changes in accordance with // `metrics.target_audio_bitrate_bps` and `metrics.overhead_bytes_per_packet`. UpdateNetworkMetrics(&controller, kTargetBitrateBps, kOverheadBytesPerPacket); CheckDecision(&controller, kInitialFrameLengthMs, kBitrateBps); } TEST(AnaBitrateControllerTest, UpdateMultipleNetworkMetricsAtOnce) { // This test is similar to ChangeBitrateOnTargetBitrateChanged. But instead of // using ::UpdateNetworkMetrics(...), which calls // BitrateController::UpdateNetworkMetrics(...) multiple times, we // we call it only once. This is to verify that // BitrateController::UpdateNetworkMetrics(...) can handle multiple // network updates at once. This is, however, not a common use case in current // audio_network_adaptor_impl.cc. constexpr int kInitialFrameLengthMs = 20; BitrateController controller( BitrateController::Config(32000, kInitialFrameLengthMs, 0, 0)); constexpr int kTargetBitrateBps = 48000; constexpr size_t kOverheadBytesPerPacket = 64; constexpr int kBitrateBps = kTargetBitrateBps - kOverheadBytesPerPacket * 8 * 1000 / kInitialFrameLengthMs; Controller::NetworkMetrics network_metrics; network_metrics.target_audio_bitrate_bps = kTargetBitrateBps; network_metrics.overhead_bytes_per_packet = kOverheadBytesPerPacket; controller.UpdateNetworkMetrics(network_metrics); CheckDecision(&controller, kInitialFrameLengthMs, kBitrateBps); } TEST(AnaBitrateControllerTest, TreatUnknownFrameLengthAsFrameLengthUnchanged) { constexpr int kInitialFrameLengthMs = 20; BitrateController controller( BitrateController::Config(32000, kInitialFrameLengthMs, 0, 0)); constexpr int kTargetBitrateBps = 48000; constexpr size_t kOverheadBytesPerPacket = 64; constexpr int kBitrateBps = kTargetBitrateBps - kOverheadBytesPerPacket * 8 * 1000 / kInitialFrameLengthMs; UpdateNetworkMetrics(&controller, kTargetBitrateBps, kOverheadBytesPerPacket); CheckDecision(&controller, absl::nullopt, kBitrateBps); } TEST(AnaBitrateControllerTest, IncreaseBitrateOnFrameLengthIncreased) { constexpr int kInitialFrameLengthMs = 20; BitrateController controller( BitrateController::Config(32000, kInitialFrameLengthMs, 0, 0)); constexpr int kTargetBitrateBps = 48000; constexpr size_t kOverheadBytesPerPacket = 64; constexpr int kBitrateBps = kTargetBitrateBps - kOverheadBytesPerPacket * 8 * 1000 / kInitialFrameLengthMs; UpdateNetworkMetrics(&controller, kTargetBitrateBps, kOverheadBytesPerPacket); CheckDecision(&controller, absl::nullopt, kBitrateBps); constexpr int kFrameLengthMs = 60; constexpr size_t kPacketOverheadRateDiff = kOverheadBytesPerPacket * 8 * 1000 / 20 - kOverheadBytesPerPacket * 8 * 1000 / 60; UpdateNetworkMetrics(&controller, kTargetBitrateBps, kOverheadBytesPerPacket); CheckDecision(&controller, kFrameLengthMs, kBitrateBps + kPacketOverheadRateDiff); } TEST(AnaBitrateControllerTest, DecreaseBitrateOnFrameLengthDecreased) { constexpr int kInitialFrameLengthMs = 60; BitrateController controller( BitrateController::Config(32000, kInitialFrameLengthMs, 0, 0)); constexpr int kTargetBitrateBps = 48000; constexpr size_t kOverheadBytesPerPacket = 64; constexpr int kBitrateBps = kTargetBitrateBps - kOverheadBytesPerPacket * 8 * 1000 / kInitialFrameLengthMs; UpdateNetworkMetrics(&controller, kTargetBitrateBps, kOverheadBytesPerPacket); CheckDecision(&controller, absl::nullopt, kBitrateBps); constexpr int kFrameLengthMs = 20; constexpr size_t kPacketOverheadRateDiff = kOverheadBytesPerPacket * 8 * 1000 / 20 - kOverheadBytesPerPacket * 8 * 1000 / 60; UpdateNetworkMetrics(&controller, kTargetBitrateBps, kOverheadBytesPerPacket); CheckDecision(&controller, kFrameLengthMs, kBitrateBps - kPacketOverheadRateDiff); } TEST(AnaBitrateControllerTest, BitrateNeverBecomesNegative) { BitrateController controller(BitrateController::Config(32000, 20, 0, 0)); constexpr size_t kOverheadBytesPerPacket = 64; constexpr int kFrameLengthMs = 60; // Set a target rate smaller than overhead rate, the bitrate is bounded by 0. constexpr int kTargetBitrateBps = kOverheadBytesPerPacket * 8 * 1000 / kFrameLengthMs - 1; UpdateNetworkMetrics(&controller, kTargetBitrateBps, kOverheadBytesPerPacket); CheckDecision(&controller, kFrameLengthMs, 0); } TEST(AnaBitrateControllerTest, CheckBehaviorOnChangingCondition) { BitrateController controller(BitrateController::Config(32000, 20, 0, 0)); // Start from an arbitrary overall bitrate. int overall_bitrate = 34567; size_t overhead_bytes_per_packet = 64; int frame_length_ms = 20; int current_bitrate = rtc::checked_cast( overall_bitrate - overhead_bytes_per_packet * 8 * 1000 / frame_length_ms); UpdateNetworkMetrics(&controller, overall_bitrate, overhead_bytes_per_packet); CheckDecision(&controller, frame_length_ms, current_bitrate); // Next: increase overall bitrate. overall_bitrate += 100; current_bitrate += 100; UpdateNetworkMetrics(&controller, overall_bitrate, overhead_bytes_per_packet); CheckDecision(&controller, frame_length_ms, current_bitrate); // Next: change frame length. frame_length_ms = 60; current_bitrate += rtc::checked_cast(overhead_bytes_per_packet * 8 * 1000 / 20 - overhead_bytes_per_packet * 8 * 1000 / 60); UpdateNetworkMetrics(&controller, overall_bitrate, overhead_bytes_per_packet); CheckDecision(&controller, frame_length_ms, current_bitrate); // Next: change overhead. overhead_bytes_per_packet -= 30; current_bitrate += 30 * 8 * 1000 / frame_length_ms; UpdateNetworkMetrics(&controller, overall_bitrate, overhead_bytes_per_packet); CheckDecision(&controller, frame_length_ms, current_bitrate); // Next: change frame length. frame_length_ms = 20; current_bitrate -= rtc::checked_cast(overhead_bytes_per_packet * 8 * 1000 / 20 - overhead_bytes_per_packet * 8 * 1000 / 60); UpdateNetworkMetrics(&controller, overall_bitrate, overhead_bytes_per_packet); CheckDecision(&controller, frame_length_ms, current_bitrate); // Next: decrease overall bitrate and frame length. overall_bitrate -= 100; current_bitrate -= 100; frame_length_ms = 60; current_bitrate += rtc::checked_cast(overhead_bytes_per_packet * 8 * 1000 / 20 - overhead_bytes_per_packet * 8 * 1000 / 60); UpdateNetworkMetrics(&controller, overall_bitrate, overhead_bytes_per_packet); CheckDecision(&controller, frame_length_ms, current_bitrate); } } // namespace audio_network_adaptor } // namespace webrtc