NetEq: Fix a bug in expand_rate and speech_expand_rate calculation
After a Merge operation, the statistics for number of samples generated using Expand must be corrected, and the correction can in fact be negative. However, a bug was introduced in https://codereview.webrtc.org/1230503003 which uses a size_t to represent the correction, which leads to wrap-around of the negative value. This is not a problem in itself, since this value is added to another size_t, with the effect that the desired subtraction happens anyway. The actual problem arises if the statistics are polled/reset before a subtraction happens -- that is, between an Expand and a Merge operation. This will lead to an actual wrap-around of the stats value, and large expand_rate (16384) is reported. BUG=webrtc:7554 Review-Url: https://codereview.webrtc.org/2859483005 Cr-Commit-Position: refs/heads/master@{#18029}
This commit is contained in:
committed by
Commit bot
parent
2a28035627
commit
2979f55f95
@ -158,6 +158,7 @@ size_t Merge::Process(int16_t* input, size_t input_length,
|
|||||||
|
|
||||||
// Return new added length. |old_length| samples were borrowed from
|
// Return new added length. |old_length| samples were borrowed from
|
||||||
// |sync_buffer_|.
|
// |sync_buffer_|.
|
||||||
|
RTC_DCHECK_GE(output_length, old_length);
|
||||||
return output_length - old_length;
|
return output_length - old_length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1600,16 +1600,18 @@ void NetEqImpl::DoMerge(int16_t* decoded_buffer, size_t decoded_length,
|
|||||||
size_t new_length = merge_->Process(decoded_buffer, decoded_length,
|
size_t new_length = merge_->Process(decoded_buffer, decoded_length,
|
||||||
mute_factor_array_.get(),
|
mute_factor_array_.get(),
|
||||||
algorithm_buffer_.get());
|
algorithm_buffer_.get());
|
||||||
size_t expand_length_correction = new_length -
|
// Correction can be negative.
|
||||||
decoded_length / algorithm_buffer_->Channels();
|
int expand_length_correction =
|
||||||
|
rtc::dchecked_cast<int>(new_length) -
|
||||||
|
rtc::dchecked_cast<int>(decoded_length / algorithm_buffer_->Channels());
|
||||||
|
|
||||||
// Update in-call and post-call statistics.
|
// Update in-call and post-call statistics.
|
||||||
if (expand_->MuteFactor(0) == 0) {
|
if (expand_->MuteFactor(0) == 0) {
|
||||||
// Expand generates only noise.
|
// Expand generates only noise.
|
||||||
stats_.ExpandedNoiseSamples(expand_length_correction);
|
stats_.ExpandedNoiseSamplesCorrection(expand_length_correction);
|
||||||
} else {
|
} else {
|
||||||
// Expansion generates more than only noise.
|
// Expansion generates more than only noise.
|
||||||
stats_.ExpandedVoiceSamples(expand_length_correction);
|
stats_.ExpandedVoiceSamplesCorrection(expand_length_correction);
|
||||||
}
|
}
|
||||||
|
|
||||||
last_mode_ = kModeMerge;
|
last_mode_ = kModeMerge;
|
||||||
|
|||||||
@ -446,11 +446,11 @@ TEST_F(NetEqDecodingTest, MAYBE_TestBitExactness) {
|
|||||||
"09fa7646e2ad032a0b156177b95f09012430f81f",
|
"09fa7646e2ad032a0b156177b95f09012430f81f",
|
||||||
"759fef89a5de52bd17e733dc255c671ce86be909");
|
"759fef89a5de52bd17e733dc255c671ce86be909");
|
||||||
|
|
||||||
const std::string network_stats_checksum = PlatformChecksum(
|
const std::string network_stats_checksum =
|
||||||
"f59b3dfdb9b1b8bbb61abedd7c8cf3fc47c21f5f",
|
PlatformChecksum("f7c2158761a531dd2804d13da0480033faa7be12",
|
||||||
"c8b2a93842e48d014f7e6efe10ae96cb3892b129",
|
"8b5e3c8247dce48cb33923eaa1a502ca91429d5e",
|
||||||
"f59b3dfdb9b1b8bbb61abedd7c8cf3fc47c21f5f",
|
"f7c2158761a531dd2804d13da0480033faa7be12",
|
||||||
"f59b3dfdb9b1b8bbb61abedd7c8cf3fc47c21f5f");
|
"f7c2158761a531dd2804d13da0480033faa7be12");
|
||||||
|
|
||||||
const std::string rtcp_stats_checksum = PlatformChecksum(
|
const std::string rtcp_stats_checksum = PlatformChecksum(
|
||||||
"b8880bf9fed2487efbddcb8d94b9937a29ae521d",
|
"b8880bf9fed2487efbddcb8d94b9937a29ae521d",
|
||||||
@ -483,11 +483,11 @@ TEST_F(NetEqDecodingTest, MAYBE_TestOpusBitExactness) {
|
|||||||
"6237dd113ad80d7764fe4c90b55b2ec035eae64e",
|
"6237dd113ad80d7764fe4c90b55b2ec035eae64e",
|
||||||
"6237dd113ad80d7764fe4c90b55b2ec035eae64e");
|
"6237dd113ad80d7764fe4c90b55b2ec035eae64e");
|
||||||
|
|
||||||
const std::string network_stats_checksum = PlatformChecksum(
|
const std::string network_stats_checksum =
|
||||||
"d8379381d5a619f0616bb3c0a8a9eea1704a8ab8",
|
PlatformChecksum("0869a450a819b14bf2a91eb6f3629a3421d17606",
|
||||||
"d8379381d5a619f0616bb3c0a8a9eea1704a8ab8",
|
"0869a450a819b14bf2a91eb6f3629a3421d17606",
|
||||||
"d8379381d5a619f0616bb3c0a8a9eea1704a8ab8",
|
"0869a450a819b14bf2a91eb6f3629a3421d17606",
|
||||||
"d8379381d5a619f0616bb3c0a8a9eea1704a8ab8");
|
"0869a450a819b14bf2a91eb6f3629a3421d17606");
|
||||||
|
|
||||||
const std::string rtcp_stats_checksum = PlatformChecksum(
|
const std::string rtcp_stats_checksum = PlatformChecksum(
|
||||||
"e37c797e3de6a64dda88c9ade7a013d022a2e1e0",
|
"e37c797e3de6a64dda88c9ade7a013d022a2e1e0",
|
||||||
|
|||||||
@ -22,6 +22,16 @@
|
|||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
size_t AddIntToSizeTWithLowerCap(int a, size_t b) {
|
||||||
|
const size_t ret = b + a;
|
||||||
|
// If a + b is negative, resulting in a negative wrap, cap it to zero instead.
|
||||||
|
static_assert(sizeof(size_t) >= sizeof(int),
|
||||||
|
"int must not be wider than size_t for this to work");
|
||||||
|
return (a < 0 && ret > b) ? 0 : ret;
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
// Allocating the static const so that it can be passed by reference to
|
// Allocating the static const so that it can be passed by reference to
|
||||||
// RTC_DCHECK.
|
// RTC_DCHECK.
|
||||||
const size_t StatisticsCalculator::kLenWaitingTimes;
|
const size_t StatisticsCalculator::kLenWaitingTimes;
|
||||||
@ -148,6 +158,16 @@ void StatisticsCalculator::ExpandedNoiseSamples(size_t num_samples) {
|
|||||||
expanded_noise_samples_ += num_samples;
|
expanded_noise_samples_ += num_samples;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void StatisticsCalculator::ExpandedVoiceSamplesCorrection(int num_samples) {
|
||||||
|
expanded_speech_samples_ =
|
||||||
|
AddIntToSizeTWithLowerCap(num_samples, expanded_speech_samples_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void StatisticsCalculator::ExpandedNoiseSamplesCorrection(int num_samples) {
|
||||||
|
expanded_noise_samples_ =
|
||||||
|
AddIntToSizeTWithLowerCap(num_samples, expanded_noise_samples_);
|
||||||
|
}
|
||||||
|
|
||||||
void StatisticsCalculator::PreemptiveExpandedSamples(size_t num_samples) {
|
void StatisticsCalculator::PreemptiveExpandedSamples(size_t num_samples) {
|
||||||
preemptive_samples_ += num_samples;
|
preemptive_samples_ += num_samples;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -45,6 +45,14 @@ class StatisticsCalculator {
|
|||||||
// that the expansion produced only noise samples.
|
// that the expansion produced only noise samples.
|
||||||
void ExpandedNoiseSamples(size_t num_samples);
|
void ExpandedNoiseSamples(size_t num_samples);
|
||||||
|
|
||||||
|
// Corrects the statistics for number of samples produced through non-noise
|
||||||
|
// expansion by adding |num_samples| (negative or positive) to the current
|
||||||
|
// value. The result is capped to zero to avoid negative values.
|
||||||
|
void ExpandedVoiceSamplesCorrection(int num_samples);
|
||||||
|
|
||||||
|
// Same as ExpandedVoiceSamplesCorrection but for noise samples.
|
||||||
|
void ExpandedNoiseSamplesCorrection(int num_samples);
|
||||||
|
|
||||||
// Reports that |num_samples| samples were produced through preemptive
|
// Reports that |num_samples| samples were produced through preemptive
|
||||||
// expansion.
|
// expansion.
|
||||||
void PreemptiveExpandedSamples(size_t num_samples);
|
void PreemptiveExpandedSamples(size_t num_samples);
|
||||||
|
|||||||
Reference in New Issue
Block a user