Revert "Change buffer level filter to store current level in number of samples."
This reverts commit 87977dd06e702ed517f26235c12e37bd927527c7. Reason for revert: Breaks downstream project Original change's description: > Change buffer level filter to store current level in number of samples. > > The buffer level should not be converted back and forth between samples and packets in case of variable packet lengths. > > Bug: webrtc:10736 > Change-Id: Ia08dcfac3d8104dc79fbad0704a5f6f12a050a01 > Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/142178 > Reviewed-by: Minyue Li <minyue@webrtc.org> > Commit-Queue: Jakob Ivarsson <jakobi@webrtc.org> > Cr-Commit-Position: refs/heads/master@{#28368} TBR=henrik.lundin@webrtc.org,minyue@webrtc.org,jakobi@webrtc.org Change-Id: I3900c9f6071fce51d13fb3b7c886157304d7a5c3 No-Presubmit: true No-Tree-Checks: true No-Try: true Bug: webrtc:10736 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/143786 Reviewed-by: Jakob Ivarsson <jakobi@webrtc.org> Commit-Queue: Jakob Ivarsson <jakobi@webrtc.org> Cr-Commit-Position: refs/heads/master@{#28369}
This commit is contained in:
committed by
Commit Bot
parent
87977dd06e
commit
d3fc161c16
@ -994,35 +994,35 @@ class AcmReceiverBitExactnessOldApi : public ::testing::Test {
|
||||
#if (defined(WEBRTC_CODEC_ISAC) || defined(WEBRTC_CODEC_ISACFX)) && \
|
||||
defined(WEBRTC_CODEC_ILBC)
|
||||
TEST_F(AcmReceiverBitExactnessOldApi, 8kHzOutput) {
|
||||
Run(8000, PlatformChecksum("bc5cc2391174c865f02d9b2ae568020a",
|
||||
"06621315b131e5ece54aff186ec7b9e4",
|
||||
"2d05bd35f4dd9798e4189d7da6e6ba10",
|
||||
Run(8000, PlatformChecksum("bcfbe2e89b4317b22e29557168edf187",
|
||||
"af15addb648cf7f032d6415672365fb3",
|
||||
"54a0008eb79537dee1d8fdaa5bc29f4b",
|
||||
"4598140b5e4f7ee66c5adad609e65a3e",
|
||||
"c0c14f9d8d4151510cafdaf78e2ebd20"));
|
||||
"3155d7f2593a3276986f36221a61783c"));
|
||||
}
|
||||
|
||||
TEST_F(AcmReceiverBitExactnessOldApi, 16kHzOutput) {
|
||||
Run(16000, PlatformChecksum("9e3893aeb5dda4f9cea6adec21d21ad8",
|
||||
"70d26c18385e05a35162460a2ef6a0e4",
|
||||
"b1ef73d7dde40033e30a76a1cc6a1ab6",
|
||||
Run(16000, PlatformChecksum("1737deef193e6c90e139ce82b7361ae4",
|
||||
"9e2a9f7728c71d6559ce3a32d2b10a5d",
|
||||
"114958862099142ac78b12100c21cb8d",
|
||||
"f2aad418af974a3b1694d5ae5cc2c3c7",
|
||||
"25ae85ea1d2d629956cec7ea0b94f51c"));
|
||||
"af2889a5ca84fb40c9aa209b9318ee7a"));
|
||||
}
|
||||
|
||||
TEST_F(AcmReceiverBitExactnessOldApi, 32kHzOutput) {
|
||||
Run(32000, PlatformChecksum("4be3e35ebfdce55157491945610ef663",
|
||||
"424fcd896d2050530648de083567aff7",
|
||||
"ab50b8546f56c359c8e4c7d74e49aae4",
|
||||
Run(32000, PlatformChecksum("1bf40ff024c6aa5b832d1d242c29cb3b",
|
||||
"3c9690cd136e9ecd1b26a22f70fe1d5c",
|
||||
"a1a3a01d8e25fcd11f1cedcd02e968b8",
|
||||
"100869c8dcde51346c2073e52a272d98",
|
||||
"87731746b160e4ae8313fa8af92bba12"));
|
||||
"33695077e9ec6bca80819ce2ba263a78"));
|
||||
}
|
||||
|
||||
TEST_F(AcmReceiverBitExactnessOldApi, 48kHzOutput) {
|
||||
Run(48000, PlatformChecksum("1df82e2f5c1c96d94ad0edc55c723d01",
|
||||
"a623e44f7e41263245361e2b8c6cedd2",
|
||||
"22d0e9c2b62f367fb2d2052569c70e55",
|
||||
Run(48000, PlatformChecksum("bf92db1e502deff5adf6fd2e6ab9a2e5",
|
||||
"c37b110ab50d87620972daee5d1eaf31",
|
||||
"5d55b68be7bcf39b60fcc74519363fb4",
|
||||
"bd44bf97e7899186532f91235cef444d",
|
||||
"c3188d9fdaa8057a98815c9b7ecc48f1"));
|
||||
"32eec738698ffe62b9777d6a349cd596"));
|
||||
}
|
||||
|
||||
TEST_F(AcmReceiverBitExactnessOldApi, 48kHzOutputExternalDecoder) {
|
||||
@ -1105,11 +1105,11 @@ TEST_F(AcmReceiverBitExactnessOldApi, 48kHzOutputExternalDecoder) {
|
||||
rtc::scoped_refptr<rtc::RefCountedObject<ADFactory>> factory(
|
||||
new rtc::RefCountedObject<ADFactory>);
|
||||
Run(48000,
|
||||
PlatformChecksum("1df82e2f5c1c96d94ad0edc55c723d01",
|
||||
"a623e44f7e41263245361e2b8c6cedd2",
|
||||
"22d0e9c2b62f367fb2d2052569c70e55",
|
||||
PlatformChecksum("bf92db1e502deff5adf6fd2e6ab9a2e5",
|
||||
"c37b110ab50d87620972daee5d1eaf31",
|
||||
"5d55b68be7bcf39b60fcc74519363fb4",
|
||||
"bd44bf97e7899186532f91235cef444d",
|
||||
"c3188d9fdaa8057a98815c9b7ecc48f1"),
|
||||
"32eec738698ffe62b9777d6a349cd596"),
|
||||
factory, [](AudioCodingModule* acm) {
|
||||
acm->SetReceiveCodecs({{0, {"MockPCMu", 8000, 1}},
|
||||
{103, {"ISAC", 16000, 1}},
|
||||
@ -1328,7 +1328,7 @@ TEST_F(AcmSenderBitExactnessOldApi, IsacWb30ms) {
|
||||
Run(AcmReceiverBitExactnessOldApi::PlatformChecksum(
|
||||
"2c9cb15d4ed55b5a0cadd04883bc73b0",
|
||||
"9336a9b993cbd8a751f0e8958e66c89c",
|
||||
"5c2eb46199994506236f68b2c8e51b0d",
|
||||
"bd4682225f7c4ad5f2049f6769713ac2",
|
||||
"343f1f42be0607c61e6516aece424609",
|
||||
"2c9cb15d4ed55b5a0cadd04883bc73b0"),
|
||||
AcmReceiverBitExactnessOldApi::PlatformChecksum(
|
||||
@ -1343,11 +1343,11 @@ TEST_F(AcmSenderBitExactnessOldApi, IsacWb30ms) {
|
||||
TEST_F(AcmSenderBitExactnessOldApi, IsacWb60ms) {
|
||||
ASSERT_NO_FATAL_FAILURE(SetUpTest("ISAC", 16000, 1, 103, 960, 960));
|
||||
Run(AcmReceiverBitExactnessOldApi::PlatformChecksum(
|
||||
"f59760fa000991ee5fa81f2e607db254",
|
||||
"986aa16d7097a26e32e212e39ec58517",
|
||||
"9a81e467eb1485f84aca796f8ea65011",
|
||||
"1ad29139a04782a33daad8c2b9b35875",
|
||||
"14d63c5f08127d280e722e3191b73bdd",
|
||||
"edcf26694c289e3d9691faf79b74f09f",
|
||||
"ef75e900e6f375e3061163c53fd09a63",
|
||||
"f59760fa000991ee5fa81f2e607db254"),
|
||||
"1ad29139a04782a33daad8c2b9b35875"),
|
||||
AcmReceiverBitExactnessOldApi::PlatformChecksum(
|
||||
"9e0a0ab743ad987b55b8e14802769c56",
|
||||
"ebe04a819d3a9d83a83a17f271e1139a",
|
||||
|
||||
@ -22,31 +22,52 @@ BufferLevelFilter::BufferLevelFilter() {
|
||||
}
|
||||
|
||||
void BufferLevelFilter::Reset() {
|
||||
filtered_current_level_ = 0.0;
|
||||
level_factor_ = 0.988;
|
||||
filtered_current_level_ = 0;
|
||||
level_factor_ = 253;
|
||||
}
|
||||
|
||||
void BufferLevelFilter::Update(size_t buffer_size_samples,
|
||||
int time_stretched_samples) {
|
||||
filtered_current_level_ = level_factor_ * filtered_current_level_ +
|
||||
(1 - level_factor_) * buffer_size_samples;
|
||||
|
||||
// Account for time-scale operations (accelerate and pre-emptive expand) and
|
||||
// make sure that the filtered value remains non-negative.
|
||||
void BufferLevelFilter::Update(size_t buffer_size_packets,
|
||||
int time_stretched_samples,
|
||||
size_t packet_len_samples) {
|
||||
// Filter:
|
||||
// |filtered_current_level_| = |level_factor_| * |filtered_current_level_| +
|
||||
// (1 - |level_factor_|) * |buffer_size_packets|
|
||||
// |level_factor_| and |filtered_current_level_| are in Q8.
|
||||
// |buffer_size_packets| is in Q0.
|
||||
filtered_current_level_ =
|
||||
std::max(0.0, filtered_current_level_ - time_stretched_samples);
|
||||
}
|
||||
((level_factor_ * filtered_current_level_) >> 8) +
|
||||
((256 - level_factor_) * rtc::dchecked_cast<int>(buffer_size_packets));
|
||||
|
||||
void BufferLevelFilter::SetTargetBufferLevel(int target_buffer_level_packets) {
|
||||
if (target_buffer_level_packets <= 1) {
|
||||
level_factor_ = 0.980;
|
||||
} else if (target_buffer_level_packets <= 3) {
|
||||
level_factor_ = 0.984;
|
||||
} else if (target_buffer_level_packets <= 7) {
|
||||
level_factor_ = 0.988;
|
||||
} else {
|
||||
level_factor_ = 0.992;
|
||||
// Account for time-scale operations (accelerate and pre-emptive expand).
|
||||
if (time_stretched_samples && packet_len_samples > 0) {
|
||||
// Time-scaling has been performed since last filter update. Subtract the
|
||||
// value of |time_stretched_samples| from |filtered_current_level_| after
|
||||
// converting |time_stretched_samples| from samples to packets in Q8.
|
||||
// Make sure that the filtered value remains non-negative.
|
||||
|
||||
int64_t time_stretched_packets =
|
||||
(int64_t{time_stretched_samples} * (1 << 8)) /
|
||||
rtc::dchecked_cast<int64_t>(packet_len_samples);
|
||||
|
||||
filtered_current_level_ = rtc::saturated_cast<int>(
|
||||
std::max<int64_t>(0, filtered_current_level_ - time_stretched_packets));
|
||||
}
|
||||
}
|
||||
|
||||
void BufferLevelFilter::SetTargetBufferLevel(int target_buffer_level) {
|
||||
if (target_buffer_level <= 1) {
|
||||
level_factor_ = 251;
|
||||
} else if (target_buffer_level <= 3) {
|
||||
level_factor_ = 252;
|
||||
} else if (target_buffer_level <= 7) {
|
||||
level_factor_ = 253;
|
||||
} else {
|
||||
level_factor_ = 254;
|
||||
}
|
||||
}
|
||||
|
||||
int BufferLevelFilter::filtered_current_level() const {
|
||||
return filtered_current_level_;
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
@ -24,24 +24,24 @@ class BufferLevelFilter {
|
||||
virtual void Reset();
|
||||
|
||||
// Updates the filter. Current buffer size is |buffer_size_packets| (Q0).
|
||||
// |time_stretched_samples| is subtracted from the filtered value (thus
|
||||
// bypassing the filter operation).
|
||||
virtual void Update(size_t buffer_size_samples, int time_stretched_samples);
|
||||
// If |time_stretched_samples| is non-zero, the value is converted to the
|
||||
// corresponding number of packets, and is subtracted from the filtered
|
||||
// value (thus bypassing the filter operation). |packet_len_samples| is the
|
||||
// number of audio samples carried in each incoming packet.
|
||||
virtual void Update(size_t buffer_size_packets,
|
||||
int time_stretched_samples,
|
||||
size_t packet_len_samples);
|
||||
|
||||
// Set the current target buffer level in number of packets (obtained from
|
||||
// Set the current target buffer level (obtained from
|
||||
// DelayManager::base_target_level()). Used to select the appropriate
|
||||
// filter coefficient.
|
||||
virtual void SetTargetBufferLevel(int target_buffer_level_packets);
|
||||
virtual void SetTargetBufferLevel(int target_buffer_level);
|
||||
|
||||
// Returns filtered current level in number of samples.
|
||||
virtual int filtered_current_level() const {
|
||||
// Round to nearest whole sample.
|
||||
return static_cast<int>(filtered_current_level_ + 0.5);
|
||||
}
|
||||
virtual int filtered_current_level() const;
|
||||
|
||||
private:
|
||||
double level_factor_; // Filter factor for the buffer level filter.
|
||||
double filtered_current_level_;
|
||||
int level_factor_; // Filter factor for the buffer level filter in Q8.
|
||||
int filtered_current_level_; // Filtered current buffer level in Q8.
|
||||
|
||||
RTC_DISALLOW_COPY_AND_ASSIGN(BufferLevelFilter);
|
||||
};
|
||||
|
||||
@ -30,22 +30,23 @@ TEST(BufferLevelFilter, ConvergenceTest) {
|
||||
for (int times = 10; times <= 50; times += 10) {
|
||||
for (int value = 100; value <= 200; value += 10) {
|
||||
filter.Reset();
|
||||
filter.SetTargetBufferLevel(1); // Makes filter coefficient 0.98.
|
||||
filter.SetTargetBufferLevel(1); // Makes filter coefficient 251/256.
|
||||
rtc::StringBuilder ss;
|
||||
ss << "times = " << times << ", value = " << value;
|
||||
SCOPED_TRACE(ss.str()); // Print out the parameter values on failure.
|
||||
for (int i = 0; i < times; ++i) {
|
||||
filter.Update(value, 0 /* time_stretched_samples */);
|
||||
filter.Update(value, 0 /* time_stretched_samples */,
|
||||
160 /* packet_len_samples */);
|
||||
}
|
||||
// Expect the filtered value to be (theoretically)
|
||||
// (1 - 0.980 ^ |times|) * |value|.
|
||||
double expected_value_double = (1 - pow(0.98, times)) * value;
|
||||
// (1 - (251/256) ^ |times|) * |value|.
|
||||
double expected_value_double = (1 - pow(251.0 / 256.0, times)) * value;
|
||||
int expected_value = static_cast<int>(expected_value_double);
|
||||
// filtered_current_level() returns the value in Q8.
|
||||
// The actual value may differ slightly from the expected value due to
|
||||
// intermediate-stage rounding errors in the filter implementation.
|
||||
// This is why we have to use EXPECT_NEAR with a tolerance of +/-1.
|
||||
EXPECT_NEAR(expected_value, filter.filtered_current_level(), 1);
|
||||
EXPECT_NEAR(expected_value, filter.filtered_current_level() >> 8, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -57,60 +58,104 @@ TEST(BufferLevelFilter, FilterFactor) {
|
||||
const int kTimes = 10;
|
||||
const int kValue = 100;
|
||||
|
||||
filter.SetTargetBufferLevel(3); // Makes filter coefficient 0.984.
|
||||
filter.SetTargetBufferLevel(3); // Makes filter coefficient 252/256.
|
||||
for (int i = 0; i < kTimes; ++i) {
|
||||
filter.Update(kValue, 0 /* time_stretched_samples */);
|
||||
filter.Update(kValue, 0 /* time_stretched_samples */,
|
||||
160 /* packet_len_samples */);
|
||||
}
|
||||
// Expect the filtered value to be
|
||||
// (1 - 0.984 ^ |kTimes|) * |kValue|.
|
||||
int expected_value = 15;
|
||||
EXPECT_EQ(expected_value, filter.filtered_current_level());
|
||||
// (1 - (252/256) ^ |kTimes|) * |kValue|.
|
||||
int expected_value = 14;
|
||||
// filtered_current_level() returns the value in Q8.
|
||||
EXPECT_EQ(expected_value, filter.filtered_current_level() >> 8);
|
||||
|
||||
filter.Reset();
|
||||
filter.SetTargetBufferLevel(7); // Makes filter coefficient 0.988.
|
||||
filter.SetTargetBufferLevel(7); // Makes filter coefficient 253/256.
|
||||
for (int i = 0; i < kTimes; ++i) {
|
||||
filter.Update(kValue, 0 /* time_stretched_samples */);
|
||||
filter.Update(kValue, 0 /* time_stretched_samples */,
|
||||
160 /* packet_len_samples */);
|
||||
}
|
||||
// Expect the filtered value to be
|
||||
// (1 - 0.988 ^ |kTimes|) * |kValue|.
|
||||
// (1 - (253/256) ^ |kTimes|) * |kValue|.
|
||||
expected_value = 11;
|
||||
EXPECT_EQ(expected_value, filter.filtered_current_level());
|
||||
// filtered_current_level() returns the value in Q8.
|
||||
EXPECT_EQ(expected_value, filter.filtered_current_level() >> 8);
|
||||
|
||||
filter.Reset();
|
||||
filter.SetTargetBufferLevel(8); // Makes filter coefficient 0.992.
|
||||
filter.SetTargetBufferLevel(8); // Makes filter coefficient 254/256.
|
||||
for (int i = 0; i < kTimes; ++i) {
|
||||
filter.Update(kValue, 0 /* time_stretched_samples */);
|
||||
filter.Update(kValue, 0 /* time_stretched_samples */,
|
||||
160 /* packet_len_samples */);
|
||||
}
|
||||
// Expect the filtered value to be
|
||||
// (1 - 0.992 ^ |kTimes|) * |kValue|.
|
||||
expected_value = 8;
|
||||
EXPECT_EQ(expected_value, filter.filtered_current_level());
|
||||
// (1 - (254/256) ^ |kTimes|) * |kValue|.
|
||||
expected_value = 7;
|
||||
// filtered_current_level() returns the value in Q8.
|
||||
EXPECT_EQ(expected_value, filter.filtered_current_level() >> 8);
|
||||
}
|
||||
|
||||
TEST(BufferLevelFilter, TimeStretchedSamples) {
|
||||
BufferLevelFilter filter;
|
||||
filter.SetTargetBufferLevel(1); // Makes filter coefficient 0.98.
|
||||
filter.SetTargetBufferLevel(1); // Makes filter coefficient 251/256.
|
||||
// Update 10 times with value 100.
|
||||
const int kTimes = 10;
|
||||
const int kValue = 100;
|
||||
const int kTimeStretchedSamples = 3;
|
||||
const int kPacketSizeSamples = 160;
|
||||
const int kNumPacketsStretched = 2;
|
||||
const int kTimeStretchedSamples = kNumPacketsStretched * kPacketSizeSamples;
|
||||
for (int i = 0; i < kTimes; ++i) {
|
||||
filter.Update(kValue, 0);
|
||||
// Packet size set to 0. Do not expect the parameter
|
||||
// |kTimeStretchedSamples| to have any effect.
|
||||
filter.Update(kValue, kTimeStretchedSamples, 0 /* packet_len_samples */);
|
||||
}
|
||||
// Expect the filtered value to be
|
||||
// (1 - 0.98 ^ |kTimes|) * |kValue|.
|
||||
const int kExpectedValue = 18;
|
||||
EXPECT_EQ(kExpectedValue, filter.filtered_current_level());
|
||||
// (1 - (251/256) ^ |kTimes|) * |kValue|.
|
||||
const int kExpectedValue = 17;
|
||||
// filtered_current_level() returns the value in Q8.
|
||||
EXPECT_EQ(kExpectedValue, filter.filtered_current_level() >> 8);
|
||||
|
||||
// Update filter again, now with non-zero value for packet length.
|
||||
// Set the current filtered value to be the input, in order to isolate the
|
||||
// impact of |kTimeStretchedSamples|.
|
||||
filter.Update(filter.filtered_current_level(), kTimeStretchedSamples);
|
||||
EXPECT_EQ(kExpectedValue - kTimeStretchedSamples,
|
||||
filter.filtered_current_level());
|
||||
filter.Update(filter.filtered_current_level() >> 8, kTimeStretchedSamples,
|
||||
kPacketSizeSamples);
|
||||
EXPECT_EQ(kExpectedValue - kNumPacketsStretched,
|
||||
filter.filtered_current_level() >> 8);
|
||||
// Try negative value and verify that we come back to the previous result.
|
||||
filter.Update(filter.filtered_current_level(), -kTimeStretchedSamples);
|
||||
EXPECT_EQ(kExpectedValue, filter.filtered_current_level());
|
||||
filter.Update(filter.filtered_current_level() >> 8, -kTimeStretchedSamples,
|
||||
kPacketSizeSamples);
|
||||
EXPECT_EQ(kExpectedValue, filter.filtered_current_level() >> 8);
|
||||
}
|
||||
|
||||
TEST(BufferLevelFilter, TimeStretchedSamplesNegativeUnevenFrames) {
|
||||
BufferLevelFilter filter;
|
||||
filter.SetTargetBufferLevel(1); // Makes filter coefficient 251/256.
|
||||
// Update 10 times with value 100.
|
||||
const int kTimes = 10;
|
||||
const int kValue = 100;
|
||||
const int kPacketSizeSamples = 160;
|
||||
const int kTimeStretchedSamples = -3.1415 * kPacketSizeSamples;
|
||||
for (int i = 0; i < kTimes; ++i) {
|
||||
// Packet size set to 0. Do not expect the parameter
|
||||
// |kTimeStretchedSamples| to have any effect.
|
||||
filter.Update(kValue, kTimeStretchedSamples, 0 /* packet_len_samples */);
|
||||
}
|
||||
// Expect the filtered value to be
|
||||
// (1 - (251/256) ^ |kTimes|) * |kValue|.
|
||||
const int kExpectedValue = 17;
|
||||
// filtered_current_level() returns the value in Q8.
|
||||
EXPECT_EQ(kExpectedValue, filter.filtered_current_level() >> 8);
|
||||
|
||||
// Update filter again, now with non-zero value for packet length.
|
||||
// Set the current filtered value to be the input, in order to isolate the
|
||||
// impact of |kTimeStretchedSamples|.
|
||||
filter.Update(filter.filtered_current_level() >> 8, kTimeStretchedSamples,
|
||||
kPacketSizeSamples);
|
||||
EXPECT_EQ(21, filter.filtered_current_level() >> 8);
|
||||
// Try negative value and verify that we come back to the previous result.
|
||||
filter.Update(filter.filtered_current_level() >> 8, -kTimeStretchedSamples,
|
||||
kPacketSizeSamples);
|
||||
EXPECT_EQ(kExpectedValue, filter.filtered_current_level() >> 8);
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
@ -113,9 +113,11 @@ Operations DecisionLogic::GetDecision(const SyncBuffer& sync_buffer,
|
||||
cng_state_ = kCngInternalOn;
|
||||
}
|
||||
|
||||
const size_t samples_left =
|
||||
sync_buffer.FutureLength() - expand.overlap_length();
|
||||
// TODO(jakobi): Use buffer span instead of num samples.
|
||||
const size_t cur_size_samples =
|
||||
packet_buffer_.NumSamplesInBuffer(decoder_frame_length);
|
||||
samples_left + packet_buffer_.NumSamplesInBuffer(decoder_frame_length);
|
||||
|
||||
prev_time_scale_ =
|
||||
prev_time_scale_ && (prev_mode == kModeAccelerateSuccess ||
|
||||
@ -173,7 +175,8 @@ Operations DecisionLogic::GetDecision(const SyncBuffer& sync_buffer,
|
||||
// if the mute factor is low enough (otherwise the expansion was short enough
|
||||
// to not be noticable).
|
||||
// Note that the MuteFactor is in Q14, so a value of 16384 corresponds to 1.
|
||||
size_t current_span = packet_buffer_.GetSpanSamples(decoder_frame_length);
|
||||
size_t current_span =
|
||||
samples_left + packet_buffer_.GetSpanSamples(decoder_frame_length);
|
||||
if ((prev_mode == kModeExpand || prev_mode == kModeCodecPlc) &&
|
||||
expand.MuteFactor(0) < 16384 / 2 &&
|
||||
current_span < static_cast<size_t>(delay_manager_->TargetLevel() *
|
||||
@ -190,9 +193,9 @@ Operations DecisionLogic::GetDecision(const SyncBuffer& sync_buffer,
|
||||
return ExpectedPacketAvailable(prev_mode, play_dtmf);
|
||||
} else if (!PacketBuffer::IsObsoleteTimestamp(
|
||||
available_timestamp, target_timestamp, five_seconds_samples)) {
|
||||
return FuturePacketAvailable(decoder_frame_length, prev_mode,
|
||||
target_timestamp, available_timestamp,
|
||||
play_dtmf, generated_noise_samples);
|
||||
return FuturePacketAvailable(
|
||||
sync_buffer, expand, decoder_frame_length, prev_mode, target_timestamp,
|
||||
available_timestamp, play_dtmf, generated_noise_samples);
|
||||
} else {
|
||||
// This implies that available_timestamp < target_timestamp, which can
|
||||
// happen when a new stream or codec is received. Signal for a reset.
|
||||
@ -212,13 +215,19 @@ void DecisionLogic::FilterBufferLevel(size_t buffer_size_samples) {
|
||||
buffer_level_filter_->SetTargetBufferLevel(
|
||||
delay_manager_->base_target_level());
|
||||
|
||||
size_t buffer_size_packets = 0;
|
||||
if (packet_length_samples_ > 0) {
|
||||
// Calculate size in packets.
|
||||
buffer_size_packets = buffer_size_samples / packet_length_samples_;
|
||||
}
|
||||
int sample_memory_local = 0;
|
||||
if (prev_time_scale_) {
|
||||
sample_memory_local = sample_memory_;
|
||||
timescale_countdown_ = tick_timer_->GetNewCountdown(kMinTimescaleInterval);
|
||||
}
|
||||
|
||||
buffer_level_filter_->Update(buffer_size_samples, sample_memory_local);
|
||||
buffer_level_filter_->Update(buffer_size_packets, sample_memory_local,
|
||||
packet_length_samples_);
|
||||
prev_time_scale_ = false;
|
||||
}
|
||||
|
||||
@ -274,22 +283,15 @@ Operations DecisionLogic::NoPacket(bool play_dtmf) {
|
||||
Operations DecisionLogic::ExpectedPacketAvailable(Modes prev_mode,
|
||||
bool play_dtmf) {
|
||||
if (!disallow_time_stretching_ && prev_mode != kModeExpand && !play_dtmf) {
|
||||
// Check criterion for time-stretching. The values are in number of packets
|
||||
// in Q8.
|
||||
// Check criterion for time-stretching.
|
||||
int low_limit, high_limit;
|
||||
delay_manager_->BufferLimits(&low_limit, &high_limit);
|
||||
int buffer_level_packets = 0;
|
||||
if (packet_length_samples_ > 0) {
|
||||
buffer_level_packets =
|
||||
((1 << 8) * buffer_level_filter_->filtered_current_level()) /
|
||||
packet_length_samples_;
|
||||
}
|
||||
if (buffer_level_packets >= high_limit << 2)
|
||||
if (buffer_level_filter_->filtered_current_level() >= high_limit << 2)
|
||||
return kFastAccelerate;
|
||||
if (TimescaleAllowed()) {
|
||||
if (buffer_level_packets >= high_limit)
|
||||
if (buffer_level_filter_->filtered_current_level() >= high_limit)
|
||||
return kAccelerate;
|
||||
if (buffer_level_packets < low_limit)
|
||||
if (buffer_level_filter_->filtered_current_level() < low_limit)
|
||||
return kPreemptiveExpand;
|
||||
}
|
||||
}
|
||||
@ -297,6 +299,8 @@ Operations DecisionLogic::ExpectedPacketAvailable(Modes prev_mode,
|
||||
}
|
||||
|
||||
Operations DecisionLogic::FuturePacketAvailable(
|
||||
const SyncBuffer& sync_buffer,
|
||||
const Expand& expand,
|
||||
size_t decoder_frame_length,
|
||||
Modes prev_mode,
|
||||
uint32_t target_timestamp,
|
||||
@ -323,8 +327,10 @@ Operations DecisionLogic::FuturePacketAvailable(
|
||||
return kNormal;
|
||||
}
|
||||
|
||||
const size_t samples_left =
|
||||
sync_buffer.FutureLength() - expand.overlap_length();
|
||||
const size_t cur_size_samples =
|
||||
packet_buffer_.NumPacketsInBuffer() * decoder_frame_length;
|
||||
samples_left + packet_buffer_.NumPacketsInBuffer() * decoder_frame_length;
|
||||
|
||||
// If previous was comfort noise, then no merge is needed.
|
||||
if (prev_mode == kModeRfc3389Cng || prev_mode == kModeCodecInternalCng) {
|
||||
@ -359,13 +365,8 @@ Operations DecisionLogic::FuturePacketAvailable(
|
||||
}
|
||||
|
||||
bool DecisionLogic::UnderTargetLevel() const {
|
||||
int buffer_level_packets = 0;
|
||||
if (packet_length_samples_ > 0) {
|
||||
buffer_level_packets =
|
||||
((1 << 8) * buffer_level_filter_->filtered_current_level()) /
|
||||
packet_length_samples_;
|
||||
}
|
||||
return buffer_level_packets <= delay_manager_->TargetLevel();
|
||||
return buffer_level_filter_->filtered_current_level() <=
|
||||
delay_manager_->TargetLevel();
|
||||
}
|
||||
|
||||
bool DecisionLogic::ReinitAfterExpands(uint32_t timestamp_leap) const {
|
||||
|
||||
@ -134,7 +134,9 @@ class DecisionLogic final {
|
||||
|
||||
// Returns the operation to do given that the expected packet is not
|
||||
// available, but a packet further into the future is at hand.
|
||||
Operations FuturePacketAvailable(size_t decoder_frame_length,
|
||||
Operations FuturePacketAvailable(const SyncBuffer& sync_buffer,
|
||||
const Expand& expand,
|
||||
size_t decoder_frame_length,
|
||||
Modes prev_mode,
|
||||
uint32_t target_timestamp,
|
||||
uint32_t available_timestamp,
|
||||
|
||||
@ -22,8 +22,10 @@ class MockBufferLevelFilter : public BufferLevelFilter {
|
||||
virtual ~MockBufferLevelFilter() { Die(); }
|
||||
MOCK_METHOD0(Die, void());
|
||||
MOCK_METHOD0(Reset, void());
|
||||
MOCK_METHOD2(Update,
|
||||
void(size_t buffer_size_samples, int time_stretched_samples));
|
||||
MOCK_METHOD3(Update,
|
||||
void(size_t buffer_size_packets,
|
||||
int time_stretched_samples,
|
||||
size_t packet_len_samples));
|
||||
MOCK_METHOD1(SetTargetBufferLevel, void(int target_buffer_level));
|
||||
MOCK_CONST_METHOD0(filtered_current_level, int());
|
||||
};
|
||||
|
||||
@ -310,12 +310,18 @@ int NetEqImpl::TargetDelayMs() const {
|
||||
|
||||
int NetEqImpl::FilteredCurrentDelayMs() const {
|
||||
rtc::CritScope lock(&crit_sect_);
|
||||
// Calculate the filtered packet buffer level in samples. The value from
|
||||
// |buffer_level_filter_| is in number of packets, represented in Q8.
|
||||
const size_t packet_buffer_samples =
|
||||
(buffer_level_filter_->filtered_current_level() *
|
||||
decoder_frame_length_) >>
|
||||
8;
|
||||
// Sum up the filtered packet buffer level with the future length of the sync
|
||||
// buffer.
|
||||
const int delay_samples = buffer_level_filter_->filtered_current_level() +
|
||||
sync_buffer_->FutureLength();
|
||||
// buffer, and divide the sum by the sample rate.
|
||||
const size_t delay_samples =
|
||||
packet_buffer_samples + sync_buffer_->FutureLength();
|
||||
// The division below will truncate. The return value is in ms.
|
||||
return delay_samples / rtc::CheckedDivExact(fs_hz_, 1000);
|
||||
return static_cast<int>(delay_samples) / rtc::CheckedDivExact(fs_hz_, 1000);
|
||||
}
|
||||
|
||||
int NetEqImpl::NetworkStatistics(NetEqNetworkStatistics* stats) {
|
||||
|
||||
@ -458,16 +458,16 @@ TEST_F(NetEqDecodingTest, MAYBE_TestBitExactness) {
|
||||
webrtc::test::ResourcePath("audio_coding/neteq_universal_new", "rtp");
|
||||
|
||||
const std::string output_checksum =
|
||||
PlatformChecksum("415cc2366810676aad27a92b7a9068e79b7e4093",
|
||||
"52411c46e946e1d50fa777bbfb4686e7161f9cc7", "not used",
|
||||
"415cc2366810676aad27a92b7a9068e79b7e4093",
|
||||
"3e02f268f3b4f3acfcc1c397214ea13d09c212fd");
|
||||
PlatformChecksum("9652cee1d6771a9cbfda821ae1bbdb41b0dd4dee",
|
||||
"54a7e32f163663c0af35bf70bf45cefc24ad62ef", "not used",
|
||||
"9652cee1d6771a9cbfda821ae1bbdb41b0dd4dee",
|
||||
"79496b0a1ef0a3824f3ee04789748a461bed643f");
|
||||
|
||||
const std::string network_stats_checksum =
|
||||
PlatformChecksum("6c8726e8699cc61535e65ef9406d339954a05cf8",
|
||||
"b9f2c862328ddb8d3ec9e79f61cc1d937ee56df6", "not used",
|
||||
"6c8726e8699cc61535e65ef9406d339954a05cf8",
|
||||
"6c8726e8699cc61535e65ef9406d339954a05cf8");
|
||||
PlatformChecksum("c59b1f9f282b6d8733cdff975e3c150ca4a47d51",
|
||||
"bca95e565996a4ffd6e2ac15736e08843bdca93b", "not used",
|
||||
"c59b1f9f282b6d8733cdff975e3c150ca4a47d51",
|
||||
"c59b1f9f282b6d8733cdff975e3c150ca4a47d51");
|
||||
|
||||
DecodeAndCompare(input_rtp_file, output_checksum, network_stats_checksum,
|
||||
FLAG_gen_ref);
|
||||
@ -486,17 +486,17 @@ TEST_F(NetEqDecodingTest, MAYBE_TestOpusBitExactness) {
|
||||
// Checksum depends on libopus being compiled with or without SSE.
|
||||
const std::string maybe_sse =
|
||||
"14a63b3c7b925c82296be4bafc71bec85f2915c2|"
|
||||
"8884ffe98700454875a88d1c3ea9b55e829a2016";
|
||||
"2c05677daa968d6c68b92adf4affb7cd9bb4d363";
|
||||
const std::string output_checksum = PlatformChecksum(
|
||||
maybe_sse, "1f76c884d16812704dec85f2b98db697108d2d9b",
|
||||
"f888efef2d0710f202f19ba167ed509609146929", maybe_sse, maybe_sse);
|
||||
maybe_sse, "b7b7ed802b0e18ee416973bf3b9ae98599b0181d",
|
||||
"5876e52dda90d5ca433c3726555b907b97c86374", maybe_sse, maybe_sse);
|
||||
|
||||
const std::string network_stats_checksum =
|
||||
PlatformChecksum("bb8d91f71873df562224fe0dc5822b5dfb030090",
|
||||
"9f858290a675c4ceabf575feb6a59bef76d62eaf",
|
||||
"12963c965d9d102ebbc1f619508e2960a1f7dbee",
|
||||
"bb8d91f71873df562224fe0dc5822b5dfb030090",
|
||||
"bb8d91f71873df562224fe0dc5822b5dfb030090");
|
||||
PlatformChecksum("adb3272498e436d1c019cbfd71610e9510c54497",
|
||||
"fa935a91abc7291db47428a2d7c5361b98713a92",
|
||||
"42106aa5267300f709f63737707ef07afd9dac61",
|
||||
"adb3272498e436d1c019cbfd71610e9510c54497",
|
||||
"adb3272498e436d1c019cbfd71610e9510c54497");
|
||||
|
||||
DecodeAndCompare(input_rtp_file, output_checksum, network_stats_checksum,
|
||||
FLAG_gen_ref);
|
||||
@ -796,7 +796,7 @@ TEST_F(NetEqDecodingTest, LongCngWithNegativeClockDriftNetworkFreeze) {
|
||||
const double kDriftFactor = 1000.0 / (1000.0 + 25.0);
|
||||
const double kNetworkFreezeTimeMs = 5000.0;
|
||||
const bool kGetAudioDuringFreezeRecovery = false;
|
||||
const int kDelayToleranceMs = 60;
|
||||
const int kDelayToleranceMs = 50;
|
||||
const int kMaxTimeToSpeechMs = 200;
|
||||
LongCngWithClockDrift(kDriftFactor, kNetworkFreezeTimeMs,
|
||||
kGetAudioDuringFreezeRecovery, kDelayToleranceMs,
|
||||
|
||||
Reference in New Issue
Block a user