Make ANA frame length controller more robust to encoder frame lengths.
Bug: webrtc:10820 Change-Id: Ic3a30976d0181de9cdd35e44d4c5439cadad4812 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/149163 Commit-Queue: Minyue Li <minyue@webrtc.org> Reviewed-by: Ivo Creusen <ivoc@webrtc.org> Reviewed-by: Henrik Lundin <henrik.lundin@webrtc.org> Cr-Commit-Position: refs/heads/master@{#28873}
This commit is contained in:
@ -75,10 +75,8 @@ void FrameLengthController::MakeDecision(AudioEncoderRuntimeConfig* config) {
|
||||
RTC_DCHECK(!config->frame_length_ms);
|
||||
|
||||
if (FrameLengthIncreasingDecision(*config)) {
|
||||
++frame_length_ms_;
|
||||
prev_decision_increase_ = true;
|
||||
} else if (FrameLengthDecreasingDecision(*config)) {
|
||||
--frame_length_ms_;
|
||||
prev_decision_increase_ = false;
|
||||
}
|
||||
config->last_fl_change_increase = prev_decision_increase_;
|
||||
@ -99,7 +97,7 @@ bool FrameLengthController::Config::FrameLengthChange::operator<(
|
||||
}
|
||||
|
||||
bool FrameLengthController::FrameLengthIncreasingDecision(
|
||||
const AudioEncoderRuntimeConfig& config) const {
|
||||
const AudioEncoderRuntimeConfig& config) {
|
||||
// Increase frame length if
|
||||
// 1. |uplink_bandwidth_bps| is known to be smaller or equal than
|
||||
// |min_encoder_bitrate_bps| plus |prevent_overuse_margin_bps| plus the
|
||||
@ -108,12 +106,17 @@ bool FrameLengthController::FrameLengthIncreasingDecision(
|
||||
// 3. |uplink_bandwidth_bps| is known to be smaller than a threshold AND
|
||||
// 4. |uplink_packet_loss_fraction| is known to be smaller than a threshold.
|
||||
|
||||
// Find next frame length to which a criterion is defined to shift from
|
||||
// current frame length.
|
||||
auto longer_frame_length_ms = std::next(frame_length_ms_);
|
||||
if (longer_frame_length_ms == config_.encoder_frame_lengths_ms.end())
|
||||
return false;
|
||||
|
||||
auto increase_threshold = config_.fl_changing_bandwidths_bps.find(
|
||||
Config::FrameLengthChange(*frame_length_ms_, *longer_frame_length_ms));
|
||||
auto increase_threshold = config_.fl_changing_bandwidths_bps.end();
|
||||
while (longer_frame_length_ms != config_.encoder_frame_lengths_ms.end()) {
|
||||
increase_threshold = config_.fl_changing_bandwidths_bps.find(
|
||||
Config::FrameLengthChange(*frame_length_ms_, *longer_frame_length_ms));
|
||||
if (increase_threshold != config_.fl_changing_bandwidths_bps.end())
|
||||
break;
|
||||
longer_frame_length_ms = std::next(longer_frame_length_ms);
|
||||
}
|
||||
|
||||
if (increase_threshold == config_.fl_changing_bandwidths_bps.end())
|
||||
return false;
|
||||
@ -134,18 +137,23 @@ bool FrameLengthController::FrameLengthIncreasingDecision(
|
||||
OverheadRateBps(*overhead_bytes_per_packet_ +
|
||||
config_.fl_increase_overhead_offset,
|
||||
*frame_length_ms_)) {
|
||||
frame_length_ms_ = longer_frame_length_ms;
|
||||
return true;
|
||||
}
|
||||
|
||||
return (uplink_bandwidth_bps_ &&
|
||||
*uplink_bandwidth_bps_ <= increase_threshold->second) &&
|
||||
(uplink_packet_loss_fraction_ &&
|
||||
*uplink_packet_loss_fraction_ <=
|
||||
config_.fl_increasing_packet_loss_fraction);
|
||||
if ((uplink_bandwidth_bps_ &&
|
||||
*uplink_bandwidth_bps_ <= increase_threshold->second) &&
|
||||
(uplink_packet_loss_fraction_ &&
|
||||
*uplink_packet_loss_fraction_ <=
|
||||
config_.fl_increasing_packet_loss_fraction)) {
|
||||
frame_length_ms_ = longer_frame_length_ms;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool FrameLengthController::FrameLengthDecreasingDecision(
|
||||
const AudioEncoderRuntimeConfig& config) const {
|
||||
const AudioEncoderRuntimeConfig& config) {
|
||||
// Decrease frame length if
|
||||
// 1. shorter frame length is available AND
|
||||
// 2. |uplink_bandwidth_bps| is known to be bigger than
|
||||
@ -154,12 +162,18 @@ bool FrameLengthController::FrameLengthDecreasingDecision(
|
||||
// one or more of the followings:
|
||||
// 3. |uplink_bandwidth_bps| is known to be larger than a threshold,
|
||||
// 4. |uplink_packet_loss_fraction| is known to be larger than a threshold,
|
||||
if (frame_length_ms_ == config_.encoder_frame_lengths_ms.begin())
|
||||
return false;
|
||||
|
||||
auto shorter_frame_length_ms = std::prev(frame_length_ms_);
|
||||
auto decrease_threshold = config_.fl_changing_bandwidths_bps.find(
|
||||
Config::FrameLengthChange(*frame_length_ms_, *shorter_frame_length_ms));
|
||||
// Find next frame length to which a criterion is defined to shift from
|
||||
// current frame length.
|
||||
auto shorter_frame_length_ms = frame_length_ms_;
|
||||
auto decrease_threshold = config_.fl_changing_bandwidths_bps.end();
|
||||
while (shorter_frame_length_ms != config_.encoder_frame_lengths_ms.begin()) {
|
||||
shorter_frame_length_ms = std::prev(shorter_frame_length_ms);
|
||||
decrease_threshold = config_.fl_changing_bandwidths_bps.find(
|
||||
Config::FrameLengthChange(*frame_length_ms_, *shorter_frame_length_ms));
|
||||
if (decrease_threshold != config_.fl_changing_bandwidths_bps.end())
|
||||
break;
|
||||
}
|
||||
|
||||
if (decrease_threshold == config_.fl_changing_bandwidths_bps.end())
|
||||
return false;
|
||||
@ -173,11 +187,15 @@ bool FrameLengthController::FrameLengthDecreasingDecision(
|
||||
return false;
|
||||
}
|
||||
|
||||
return (uplink_bandwidth_bps_ &&
|
||||
*uplink_bandwidth_bps_ >= decrease_threshold->second) ||
|
||||
(uplink_packet_loss_fraction_ &&
|
||||
*uplink_packet_loss_fraction_ >=
|
||||
config_.fl_decreasing_packet_loss_fraction);
|
||||
if ((uplink_bandwidth_bps_ &&
|
||||
*uplink_bandwidth_bps_ >= decrease_threshold->second) ||
|
||||
(uplink_packet_loss_fraction_ &&
|
||||
*uplink_packet_loss_fraction_ >=
|
||||
config_.fl_decreasing_packet_loss_fraction)) {
|
||||
frame_length_ms_ = shorter_frame_length_ms;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
|
@ -67,11 +67,9 @@ class FrameLengthController final : public Controller {
|
||||
void MakeDecision(AudioEncoderRuntimeConfig* config) override;
|
||||
|
||||
private:
|
||||
bool FrameLengthIncreasingDecision(
|
||||
const AudioEncoderRuntimeConfig& config) const;
|
||||
bool FrameLengthIncreasingDecision(const AudioEncoderRuntimeConfig& config);
|
||||
|
||||
bool FrameLengthDecreasingDecision(
|
||||
const AudioEncoderRuntimeConfig& config) const;
|
||||
bool FrameLengthDecreasingDecision(const AudioEncoderRuntimeConfig& config);
|
||||
|
||||
const Config config_;
|
||||
|
||||
|
@ -34,6 +34,7 @@ constexpr int kMediumBandwidthBps =
|
||||
(kFl60msTo20msBandwidthBps + kFl20msTo60msBandwidthBps) / 2;
|
||||
constexpr float kMediumPacketLossFraction =
|
||||
(kFlDecreasingPacketLossFraction + kFlIncreasingPacketLossFraction) / 2;
|
||||
const std::set<int> kDefaultEncoderFrameLengthsMs = {20, 40, 60, 120};
|
||||
|
||||
int VeryLowBitrate(int frame_length_ms) {
|
||||
return kMinEncoderBitrateBps + kPreventOveruseMarginBps +
|
||||
@ -112,16 +113,16 @@ void CheckDecision(FrameLengthController* controller,
|
||||
} // namespace
|
||||
|
||||
TEST(FrameLengthControllerTest, DecreaseTo20MsOnHighUplinkBandwidth) {
|
||||
auto controller =
|
||||
CreateController(CreateChangeCriteriaFor20msAnd60ms(), {20, 60}, 60);
|
||||
auto controller = CreateController(CreateChangeCriteriaFor20msAnd60ms(),
|
||||
kDefaultEncoderFrameLengthsMs, 60);
|
||||
UpdateNetworkMetrics(controller.get(), kFl60msTo20msBandwidthBps,
|
||||
absl::nullopt, kOverheadBytesPerPacket);
|
||||
CheckDecision(controller.get(), 20);
|
||||
}
|
||||
|
||||
TEST(FrameLengthControllerTest, DecreaseTo20MsOnHighUplinkPacketLossFraction) {
|
||||
auto controller =
|
||||
CreateController(CreateChangeCriteriaFor20msAnd60ms(), {20, 60}, 60);
|
||||
auto controller = CreateController(CreateChangeCriteriaFor20msAnd60ms(),
|
||||
kDefaultEncoderFrameLengthsMs, 60);
|
||||
UpdateNetworkMetrics(controller.get(), absl::nullopt,
|
||||
kFlDecreasingPacketLossFraction,
|
||||
kOverheadBytesPerPacket);
|
||||
@ -142,8 +143,8 @@ TEST(FrameLengthControllerTest, Maintain60MsOnMultipleConditions) {
|
||||
// 1. |uplink_bandwidth_bps| is at medium level,
|
||||
// 2. |uplink_packet_loss_fraction| is at medium,
|
||||
// 3. FEC is not decided ON.
|
||||
auto controller =
|
||||
CreateController(CreateChangeCriteriaFor20msAnd60ms(), {20, 60}, 60);
|
||||
auto controller = CreateController(CreateChangeCriteriaFor20msAnd60ms(),
|
||||
kDefaultEncoderFrameLengthsMs, 60);
|
||||
UpdateNetworkMetrics(controller.get(), kMediumBandwidthBps,
|
||||
kMediumPacketLossFraction, kOverheadBytesPerPacket);
|
||||
CheckDecision(controller.get(), 60);
|
||||
@ -155,8 +156,8 @@ TEST(FrameLengthControllerTest, IncreaseTo60MsOnMultipleConditions) {
|
||||
// 2. |uplink_packet_loss_fraction| is known to be smaller than a threshold
|
||||
// AND
|
||||
// 3. FEC is not decided or OFF.
|
||||
auto controller =
|
||||
CreateController(CreateChangeCriteriaFor20msAnd60ms(), {20, 60}, 20);
|
||||
auto controller = CreateController(CreateChangeCriteriaFor20msAnd60ms(),
|
||||
kDefaultEncoderFrameLengthsMs, 20);
|
||||
UpdateNetworkMetrics(controller.get(), kFl20msTo60msBandwidthBps,
|
||||
kFlIncreasingPacketLossFraction,
|
||||
kOverheadBytesPerPacket);
|
||||
@ -164,8 +165,8 @@ TEST(FrameLengthControllerTest, IncreaseTo60MsOnMultipleConditions) {
|
||||
}
|
||||
|
||||
TEST(FrameLengthControllerTest, IncreaseTo60MsOnVeryLowUplinkBandwidth) {
|
||||
auto controller =
|
||||
CreateController(CreateChangeCriteriaFor20msAnd60ms(), {20, 60}, 20);
|
||||
auto controller = CreateController(CreateChangeCriteriaFor20msAnd60ms(),
|
||||
kDefaultEncoderFrameLengthsMs, 20);
|
||||
// We set packet loss fraction to kFlDecreasingPacketLossFraction, which
|
||||
// should have prevented frame length to increase, if the uplink bandwidth
|
||||
// was not this low.
|
||||
@ -176,8 +177,8 @@ TEST(FrameLengthControllerTest, IncreaseTo60MsOnVeryLowUplinkBandwidth) {
|
||||
}
|
||||
|
||||
TEST(FrameLengthControllerTest, Maintain60MsOnVeryLowUplinkBandwidth) {
|
||||
auto controller =
|
||||
CreateController(CreateChangeCriteriaFor20msAnd60ms(), {20, 60}, 60);
|
||||
auto controller = CreateController(CreateChangeCriteriaFor20msAnd60ms(),
|
||||
kDefaultEncoderFrameLengthsMs, 60);
|
||||
// We set packet loss fraction to FlDecreasingPacketLossFraction, which should
|
||||
// have caused the frame length to decrease, if the uplink bandwidth was not
|
||||
// this low.
|
||||
@ -195,8 +196,8 @@ TEST(FrameLengthControllerTest, UpdateMultipleNetworkMetricsAtOnce) {
|
||||
// FrameLengthController::UpdateNetworkMetrics(...) can handle multiple
|
||||
// network updates at once. This is, however, not a common use case in current
|
||||
// audio_network_adaptor_impl.cc.
|
||||
auto controller =
|
||||
CreateController(CreateChangeCriteriaFor20msAnd60ms(), {20, 60}, 20);
|
||||
auto controller = CreateController(CreateChangeCriteriaFor20msAnd60ms(),
|
||||
kDefaultEncoderFrameLengthsMs, 20);
|
||||
Controller::NetworkMetrics network_metrics;
|
||||
network_metrics.uplink_bandwidth_bps = kFl20msTo60msBandwidthBps;
|
||||
network_metrics.uplink_packet_loss_fraction = kFlIncreasingPacketLossFraction;
|
||||
@ -217,8 +218,8 @@ TEST(FrameLengthControllerTest,
|
||||
}
|
||||
|
||||
TEST(FrameLengthControllerTest, Maintain20MsOnMediumUplinkBandwidth) {
|
||||
auto controller =
|
||||
CreateController(CreateChangeCriteriaFor20msAnd60ms(), {20, 60}, 20);
|
||||
auto controller = CreateController(CreateChangeCriteriaFor20msAnd60ms(),
|
||||
kDefaultEncoderFrameLengthsMs, 20);
|
||||
UpdateNetworkMetrics(controller.get(), kMediumBandwidthBps,
|
||||
kFlIncreasingPacketLossFraction,
|
||||
kOverheadBytesPerPacket);
|
||||
@ -226,8 +227,8 @@ TEST(FrameLengthControllerTest, Maintain20MsOnMediumUplinkBandwidth) {
|
||||
}
|
||||
|
||||
TEST(FrameLengthControllerTest, Maintain20MsOnMediumUplinkPacketLossFraction) {
|
||||
auto controller =
|
||||
CreateController(CreateChangeCriteriaFor20msAnd60ms(), {20, 60}, 20);
|
||||
auto controller = CreateController(CreateChangeCriteriaFor20msAnd60ms(),
|
||||
kDefaultEncoderFrameLengthsMs, 20);
|
||||
// Use a low uplink bandwidth that would cause frame length to increase if
|
||||
// uplink packet loss fraction was low.
|
||||
UpdateNetworkMetrics(controller.get(), kFl20msTo60msBandwidthBps,
|
||||
@ -236,8 +237,8 @@ TEST(FrameLengthControllerTest, Maintain20MsOnMediumUplinkPacketLossFraction) {
|
||||
}
|
||||
|
||||
TEST(FrameLengthControllerTest, Maintain60MsWhenNo120msCriteriaIsSet) {
|
||||
auto controller =
|
||||
CreateController(CreateChangeCriteriaFor20msAnd60ms(), {20, 60, 120}, 60);
|
||||
auto controller = CreateController(CreateChangeCriteriaFor20msAnd60ms(),
|
||||
kDefaultEncoderFrameLengthsMs, 60);
|
||||
UpdateNetworkMetrics(controller.get(), kFl60msTo120msBandwidthBps,
|
||||
kFlIncreasingPacketLossFraction,
|
||||
kOverheadBytesPerPacket);
|
||||
@ -246,7 +247,7 @@ TEST(FrameLengthControllerTest, Maintain60MsWhenNo120msCriteriaIsSet) {
|
||||
|
||||
TEST(FrameLengthControllerTest, From120MsTo20MsOnHighUplinkBandwidth) {
|
||||
auto controller = CreateController(CreateChangeCriteriaFor20ms60msAnd120ms(),
|
||||
{20, 60, 120}, 120);
|
||||
kDefaultEncoderFrameLengthsMs, 120);
|
||||
// It takes two steps for frame length to go from 120ms to 20ms.
|
||||
UpdateNetworkMetrics(controller.get(), kFl60msTo20msBandwidthBps,
|
||||
absl::nullopt, kOverheadBytesPerPacket);
|
||||
@ -259,7 +260,7 @@ TEST(FrameLengthControllerTest, From120MsTo20MsOnHighUplinkBandwidth) {
|
||||
|
||||
TEST(FrameLengthControllerTest, From120MsTo20MsOnHighUplinkPacketLossFraction) {
|
||||
auto controller = CreateController(CreateChangeCriteriaFor20ms60msAnd120ms(),
|
||||
{20, 60, 120}, 120);
|
||||
kDefaultEncoderFrameLengthsMs, 120);
|
||||
// It takes two steps for frame length to go from 120ms to 20ms.
|
||||
UpdateNetworkMetrics(controller.get(), absl::nullopt,
|
||||
kFlDecreasingPacketLossFraction,
|
||||
@ -274,7 +275,7 @@ TEST(FrameLengthControllerTest, From120MsTo20MsOnHighUplinkPacketLossFraction) {
|
||||
|
||||
TEST(FrameLengthControllerTest, Maintain120MsOnVeryLowUplinkBandwidth) {
|
||||
auto controller = CreateController(CreateChangeCriteriaFor20ms60msAnd120ms(),
|
||||
{20, 60, 120}, 120);
|
||||
kDefaultEncoderFrameLengthsMs, 120);
|
||||
// We set packet loss fraction to FlDecreasingPacketLossFraction, which should
|
||||
// have caused the frame length to decrease, if the uplink bandwidth was not
|
||||
// this low.
|
||||
@ -286,7 +287,7 @@ TEST(FrameLengthControllerTest, Maintain120MsOnVeryLowUplinkBandwidth) {
|
||||
|
||||
TEST(FrameLengthControllerTest, From60MsTo120MsOnVeryLowUplinkBandwidth) {
|
||||
auto controller = CreateController(CreateChangeCriteriaFor20ms60msAnd120ms(),
|
||||
{20, 60, 120}, 60);
|
||||
kDefaultEncoderFrameLengthsMs, 60);
|
||||
// We set packet loss fraction to FlDecreasingPacketLossFraction, which should
|
||||
// have prevented frame length to increase, if the uplink bandwidth was not
|
||||
// this low.
|
||||
@ -301,7 +302,7 @@ TEST(FrameLengthControllerTest, From20MsTo120MsOnMultipleConditions) {
|
||||
// 1. |uplink_bandwidth_bps| is known to be smaller than a threshold AND
|
||||
// 2. |uplink_packet_loss_fraction| is known to be smaller than a threshold.
|
||||
auto controller = CreateController(CreateChangeCriteriaFor20ms60msAnd120ms(),
|
||||
{20, 60, 120}, 20);
|
||||
kDefaultEncoderFrameLengthsMs, 20);
|
||||
// It takes two steps for frame length to go from 20ms to 120ms.
|
||||
UpdateNetworkMetrics(controller.get(), kFl60msTo120msBandwidthBps,
|
||||
kFlIncreasingPacketLossFraction,
|
||||
@ -328,7 +329,7 @@ TEST(FrameLengthControllerTest, Stall60MsIf120MsNotInReceiverFrameLengthRange) {
|
||||
|
||||
TEST(FrameLengthControllerTest, CheckBehaviorOnChangingNetworkMetrics) {
|
||||
auto controller = CreateController(CreateChangeCriteriaFor20ms60msAnd120ms(),
|
||||
{20, 60, 120}, 20);
|
||||
kDefaultEncoderFrameLengthsMs, 20);
|
||||
UpdateNetworkMetrics(controller.get(), kMediumBandwidthBps,
|
||||
kFlIncreasingPacketLossFraction,
|
||||
kOverheadBytesPerPacket);
|
||||
|
@ -55,10 +55,10 @@ constexpr int kDefaultMaxPlaybackRate = 48000;
|
||||
|
||||
// These two lists must be sorted from low to high
|
||||
#if WEBRTC_OPUS_SUPPORT_120MS_PTIME
|
||||
constexpr int kANASupportedFrameLengths[] = {20, 60, 120};
|
||||
constexpr int kANASupportedFrameLengths[] = {20, 40, 60, 120};
|
||||
constexpr int kOpusSupportedFrameLengths[] = {10, 20, 40, 60, 120};
|
||||
#else
|
||||
constexpr int kANASupportedFrameLengths[] = {20, 60};
|
||||
constexpr int kANASupportedFrameLengths[] = {20, 40, 60};
|
||||
constexpr int kOpusSupportedFrameLengths[] = {10, 20, 40, 60};
|
||||
#endif
|
||||
|
||||
|
@ -334,9 +334,11 @@ TEST_P(AudioEncoderOpusTest, SetReceiverFrameLengthRange) {
|
||||
ElementsAre(states->encoder->next_frame_length_ms()));
|
||||
states->encoder->SetReceiverFrameLengthRange(0, 12345);
|
||||
states->encoder->SetReceiverFrameLengthRange(21, 60);
|
||||
EXPECT_THAT(states->encoder->supported_frame_lengths_ms(), ElementsAre(60));
|
||||
EXPECT_THAT(states->encoder->supported_frame_lengths_ms(),
|
||||
ElementsAre(40, 60));
|
||||
states->encoder->SetReceiverFrameLengthRange(20, 59);
|
||||
EXPECT_THAT(states->encoder->supported_frame_lengths_ms(), ElementsAre(20));
|
||||
EXPECT_THAT(states->encoder->supported_frame_lengths_ms(),
|
||||
ElementsAre(20, 40));
|
||||
}
|
||||
|
||||
TEST_P(AudioEncoderOpusTest,
|
||||
@ -780,9 +782,9 @@ TEST(AudioEncoderOpusTest, TestConfigFromInvalidParams) {
|
||||
const webrtc::SdpAudioFormat format("opus", 48000, 2);
|
||||
const auto default_config = *AudioEncoderOpus::SdpToConfig(format);
|
||||
#if WEBRTC_OPUS_SUPPORT_120MS_PTIME
|
||||
const std::vector<int> default_supported_frame_lengths_ms({20, 60, 120});
|
||||
const std::vector<int> default_supported_frame_lengths_ms({20, 40, 60, 120});
|
||||
#else
|
||||
const std::vector<int> default_supported_frame_lengths_ms({20, 60});
|
||||
const std::vector<int> default_supported_frame_lengths_ms({20, 40, 60});
|
||||
#endif
|
||||
|
||||
AudioEncoderOpusConfig config;
|
||||
|
Reference in New Issue
Block a user