From 87977dd06e702ed517f26235c12e37bd927527c7 Mon Sep 17 00:00:00 2001 From: Jakob Ivarsson Date: Mon, 24 Jun 2019 13:21:30 +0200 Subject: [PATCH] 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 Commit-Queue: Jakob Ivarsson Cr-Commit-Position: refs/heads/master@{#28368} --- .../acm2/audio_coding_module_unittest.cc | 50 ++++----- .../audio_coding/neteq/buffer_level_filter.cc | 57 +++------- .../audio_coding/neteq/buffer_level_filter.h | 24 ++-- .../neteq/buffer_level_filter_unittest.cc | 105 +++++------------- modules/audio_coding/neteq/decision_logic.cc | 51 +++++---- modules/audio_coding/neteq/decision_logic.h | 4 +- .../neteq/mock/mock_buffer_level_filter.h | 6 +- modules/audio_coding/neteq/neteq_impl.cc | 14 +-- modules/audio_coding/neteq/neteq_unittest.cc | 34 +++--- 9 files changed, 134 insertions(+), 211 deletions(-) diff --git a/modules/audio_coding/acm2/audio_coding_module_unittest.cc b/modules/audio_coding/acm2/audio_coding_module_unittest.cc index c95091f1c3..f9488a34b7 100644 --- a/modules/audio_coding/acm2/audio_coding_module_unittest.cc +++ b/modules/audio_coding/acm2/audio_coding_module_unittest.cc @@ -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("bcfbe2e89b4317b22e29557168edf187", - "af15addb648cf7f032d6415672365fb3", - "54a0008eb79537dee1d8fdaa5bc29f4b", + Run(8000, PlatformChecksum("bc5cc2391174c865f02d9b2ae568020a", + "06621315b131e5ece54aff186ec7b9e4", + "2d05bd35f4dd9798e4189d7da6e6ba10", "4598140b5e4f7ee66c5adad609e65a3e", - "3155d7f2593a3276986f36221a61783c")); + "c0c14f9d8d4151510cafdaf78e2ebd20")); } TEST_F(AcmReceiverBitExactnessOldApi, 16kHzOutput) { - Run(16000, PlatformChecksum("1737deef193e6c90e139ce82b7361ae4", - "9e2a9f7728c71d6559ce3a32d2b10a5d", - "114958862099142ac78b12100c21cb8d", + Run(16000, PlatformChecksum("9e3893aeb5dda4f9cea6adec21d21ad8", + "70d26c18385e05a35162460a2ef6a0e4", + "b1ef73d7dde40033e30a76a1cc6a1ab6", "f2aad418af974a3b1694d5ae5cc2c3c7", - "af2889a5ca84fb40c9aa209b9318ee7a")); + "25ae85ea1d2d629956cec7ea0b94f51c")); } TEST_F(AcmReceiverBitExactnessOldApi, 32kHzOutput) { - Run(32000, PlatformChecksum("1bf40ff024c6aa5b832d1d242c29cb3b", - "3c9690cd136e9ecd1b26a22f70fe1d5c", - "a1a3a01d8e25fcd11f1cedcd02e968b8", + Run(32000, PlatformChecksum("4be3e35ebfdce55157491945610ef663", + "424fcd896d2050530648de083567aff7", + "ab50b8546f56c359c8e4c7d74e49aae4", "100869c8dcde51346c2073e52a272d98", - "33695077e9ec6bca80819ce2ba263a78")); + "87731746b160e4ae8313fa8af92bba12")); } TEST_F(AcmReceiverBitExactnessOldApi, 48kHzOutput) { - Run(48000, PlatformChecksum("bf92db1e502deff5adf6fd2e6ab9a2e5", - "c37b110ab50d87620972daee5d1eaf31", - "5d55b68be7bcf39b60fcc74519363fb4", + Run(48000, PlatformChecksum("1df82e2f5c1c96d94ad0edc55c723d01", + "a623e44f7e41263245361e2b8c6cedd2", + "22d0e9c2b62f367fb2d2052569c70e55", "bd44bf97e7899186532f91235cef444d", - "32eec738698ffe62b9777d6a349cd596")); + "c3188d9fdaa8057a98815c9b7ecc48f1")); } TEST_F(AcmReceiverBitExactnessOldApi, 48kHzOutputExternalDecoder) { @@ -1105,11 +1105,11 @@ TEST_F(AcmReceiverBitExactnessOldApi, 48kHzOutputExternalDecoder) { rtc::scoped_refptr> factory( new rtc::RefCountedObject); Run(48000, - PlatformChecksum("bf92db1e502deff5adf6fd2e6ab9a2e5", - "c37b110ab50d87620972daee5d1eaf31", - "5d55b68be7bcf39b60fcc74519363fb4", + PlatformChecksum("1df82e2f5c1c96d94ad0edc55c723d01", + "a623e44f7e41263245361e2b8c6cedd2", + "22d0e9c2b62f367fb2d2052569c70e55", "bd44bf97e7899186532f91235cef444d", - "32eec738698ffe62b9777d6a349cd596"), + "c3188d9fdaa8057a98815c9b7ecc48f1"), 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", - "bd4682225f7c4ad5f2049f6769713ac2", + "5c2eb46199994506236f68b2c8e51b0d", "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( - "1ad29139a04782a33daad8c2b9b35875", - "14d63c5f08127d280e722e3191b73bdd", - "edcf26694c289e3d9691faf79b74f09f", + "f59760fa000991ee5fa81f2e607db254", + "986aa16d7097a26e32e212e39ec58517", + "9a81e467eb1485f84aca796f8ea65011", "ef75e900e6f375e3061163c53fd09a63", - "1ad29139a04782a33daad8c2b9b35875"), + "f59760fa000991ee5fa81f2e607db254"), AcmReceiverBitExactnessOldApi::PlatformChecksum( "9e0a0ab743ad987b55b8e14802769c56", "ebe04a819d3a9d83a83a17f271e1139a", diff --git a/modules/audio_coding/neteq/buffer_level_filter.cc b/modules/audio_coding/neteq/buffer_level_filter.cc index 2f96618536..675091d371 100644 --- a/modules/audio_coding/neteq/buffer_level_filter.cc +++ b/modules/audio_coding/neteq/buffer_level_filter.cc @@ -22,52 +22,31 @@ BufferLevelFilter::BufferLevelFilter() { } void BufferLevelFilter::Reset() { - filtered_current_level_ = 0; - level_factor_ = 253; + filtered_current_level_ = 0.0; + level_factor_ = 0.988; } -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. +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. filtered_current_level_ = - ((level_factor_ * filtered_current_level_) >> 8) + - ((256 - level_factor_) * rtc::dchecked_cast(buffer_size_packets)); - - // 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(packet_len_samples); - - filtered_current_level_ = rtc::saturated_cast( - std::max(0, filtered_current_level_ - time_stretched_packets)); - } + std::max(0.0, filtered_current_level_ - time_stretched_samples); } -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; +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_ = 254; + level_factor_ = 0.992; } } -int BufferLevelFilter::filtered_current_level() const { - return filtered_current_level_; -} - } // namespace webrtc diff --git a/modules/audio_coding/neteq/buffer_level_filter.h b/modules/audio_coding/neteq/buffer_level_filter.h index 83388fb4f5..18b43a3806 100644 --- a/modules/audio_coding/neteq/buffer_level_filter.h +++ b/modules/audio_coding/neteq/buffer_level_filter.h @@ -24,24 +24,24 @@ class BufferLevelFilter { virtual void Reset(); // Updates the filter. Current buffer size is |buffer_size_packets| (Q0). - // 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); + // |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); - // Set the current target buffer level (obtained from + // Set the current target buffer level in number of packets (obtained from // DelayManager::base_target_level()). Used to select the appropriate // filter coefficient. - virtual void SetTargetBufferLevel(int target_buffer_level); + virtual void SetTargetBufferLevel(int target_buffer_level_packets); - virtual int filtered_current_level() const; + // Returns filtered current level in number of samples. + virtual int filtered_current_level() const { + // Round to nearest whole sample. + return static_cast(filtered_current_level_ + 0.5); + } private: - int level_factor_; // Filter factor for the buffer level filter in Q8. - int filtered_current_level_; // Filtered current buffer level in Q8. + double level_factor_; // Filter factor for the buffer level filter. + double filtered_current_level_; RTC_DISALLOW_COPY_AND_ASSIGN(BufferLevelFilter); }; diff --git a/modules/audio_coding/neteq/buffer_level_filter_unittest.cc b/modules/audio_coding/neteq/buffer_level_filter_unittest.cc index 1f12e73d10..0d4a0f29aa 100644 --- a/modules/audio_coding/neteq/buffer_level_filter_unittest.cc +++ b/modules/audio_coding/neteq/buffer_level_filter_unittest.cc @@ -30,23 +30,22 @@ 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 251/256. + filter.SetTargetBufferLevel(1); // Makes filter coefficient 0.98. 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 */, - 160 /* packet_len_samples */); + filter.Update(value, 0 /* time_stretched_samples */); } // Expect the filtered value to be (theoretically) - // (1 - (251/256) ^ |times|) * |value|. - double expected_value_double = (1 - pow(251.0 / 256.0, times)) * value; + // (1 - 0.980 ^ |times|) * |value|. + double expected_value_double = (1 - pow(0.98, times)) * value; int expected_value = static_cast(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() >> 8, 1); + EXPECT_NEAR(expected_value, filter.filtered_current_level(), 1); } } } @@ -58,104 +57,60 @@ TEST(BufferLevelFilter, FilterFactor) { const int kTimes = 10; const int kValue = 100; - filter.SetTargetBufferLevel(3); // Makes filter coefficient 252/256. + filter.SetTargetBufferLevel(3); // Makes filter coefficient 0.984. for (int i = 0; i < kTimes; ++i) { - filter.Update(kValue, 0 /* time_stretched_samples */, - 160 /* packet_len_samples */); + filter.Update(kValue, 0 /* time_stretched_samples */); } // Expect the filtered value to be - // (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); + // (1 - 0.984 ^ |kTimes|) * |kValue|. + int expected_value = 15; + EXPECT_EQ(expected_value, filter.filtered_current_level()); filter.Reset(); - filter.SetTargetBufferLevel(7); // Makes filter coefficient 253/256. + filter.SetTargetBufferLevel(7); // Makes filter coefficient 0.988. for (int i = 0; i < kTimes; ++i) { - filter.Update(kValue, 0 /* time_stretched_samples */, - 160 /* packet_len_samples */); + filter.Update(kValue, 0 /* time_stretched_samples */); } // Expect the filtered value to be - // (1 - (253/256) ^ |kTimes|) * |kValue|. + // (1 - 0.988 ^ |kTimes|) * |kValue|. expected_value = 11; - // filtered_current_level() returns the value in Q8. - EXPECT_EQ(expected_value, filter.filtered_current_level() >> 8); + EXPECT_EQ(expected_value, filter.filtered_current_level()); filter.Reset(); - filter.SetTargetBufferLevel(8); // Makes filter coefficient 254/256. + filter.SetTargetBufferLevel(8); // Makes filter coefficient 0.992. for (int i = 0; i < kTimes; ++i) { - filter.Update(kValue, 0 /* time_stretched_samples */, - 160 /* packet_len_samples */); + filter.Update(kValue, 0 /* time_stretched_samples */); } // Expect the filtered value to be - // (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); + // (1 - 0.992 ^ |kTimes|) * |kValue|. + expected_value = 8; + EXPECT_EQ(expected_value, filter.filtered_current_level()); } TEST(BufferLevelFilter, TimeStretchedSamples) { BufferLevelFilter filter; - filter.SetTargetBufferLevel(1); // Makes filter coefficient 251/256. + filter.SetTargetBufferLevel(1); // Makes filter coefficient 0.98. // Update 10 times with value 100. const int kTimes = 10; const int kValue = 100; - const int kPacketSizeSamples = 160; - const int kNumPacketsStretched = 2; - const int kTimeStretchedSamples = kNumPacketsStretched * kPacketSizeSamples; + const int kTimeStretchedSamples = 3; 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 */); + filter.Update(kValue, 0); } // 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); + // (1 - 0.98 ^ |kTimes|) * |kValue|. + const int kExpectedValue = 18; + EXPECT_EQ(kExpectedValue, filter.filtered_current_level()); // 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(kExpectedValue - kNumPacketsStretched, - filter.filtered_current_level() >> 8); + filter.Update(filter.filtered_current_level(), kTimeStretchedSamples); + EXPECT_EQ(kExpectedValue - kTimeStretchedSamples, + filter.filtered_current_level()); // 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); -} - -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); + filter.Update(filter.filtered_current_level(), -kTimeStretchedSamples); + EXPECT_EQ(kExpectedValue, filter.filtered_current_level()); } } // namespace webrtc diff --git a/modules/audio_coding/neteq/decision_logic.cc b/modules/audio_coding/neteq/decision_logic.cc index 40e421d672..f9f420af0e 100644 --- a/modules/audio_coding/neteq/decision_logic.cc +++ b/modules/audio_coding/neteq/decision_logic.cc @@ -113,11 +113,9 @@ 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 = - samples_left + packet_buffer_.NumSamplesInBuffer(decoder_frame_length); + packet_buffer_.NumSamplesInBuffer(decoder_frame_length); prev_time_scale_ = prev_time_scale_ && (prev_mode == kModeAccelerateSuccess || @@ -175,8 +173,7 @@ 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 = - samples_left + packet_buffer_.GetSpanSamples(decoder_frame_length); + size_t current_span = packet_buffer_.GetSpanSamples(decoder_frame_length); if ((prev_mode == kModeExpand || prev_mode == kModeCodecPlc) && expand.MuteFactor(0) < 16384 / 2 && current_span < static_cast(delay_manager_->TargetLevel() * @@ -193,9 +190,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( - sync_buffer, expand, decoder_frame_length, prev_mode, target_timestamp, - available_timestamp, play_dtmf, generated_noise_samples); + return FuturePacketAvailable(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. @@ -215,19 +212,13 @@ 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_packets, sample_memory_local, - packet_length_samples_); + buffer_level_filter_->Update(buffer_size_samples, sample_memory_local); prev_time_scale_ = false; } @@ -283,15 +274,22 @@ 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. + // Check criterion for time-stretching. The values are in number of packets + // in Q8. int low_limit, high_limit; delay_manager_->BufferLimits(&low_limit, &high_limit); - if (buffer_level_filter_->filtered_current_level() >= high_limit << 2) + 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) return kFastAccelerate; if (TimescaleAllowed()) { - if (buffer_level_filter_->filtered_current_level() >= high_limit) + if (buffer_level_packets >= high_limit) return kAccelerate; - if (buffer_level_filter_->filtered_current_level() < low_limit) + if (buffer_level_packets < low_limit) return kPreemptiveExpand; } } @@ -299,8 +297,6 @@ 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, @@ -327,10 +323,8 @@ Operations DecisionLogic::FuturePacketAvailable( return kNormal; } - const size_t samples_left = - sync_buffer.FutureLength() - expand.overlap_length(); const size_t cur_size_samples = - samples_left + packet_buffer_.NumPacketsInBuffer() * decoder_frame_length; + packet_buffer_.NumPacketsInBuffer() * decoder_frame_length; // If previous was comfort noise, then no merge is needed. if (prev_mode == kModeRfc3389Cng || prev_mode == kModeCodecInternalCng) { @@ -365,8 +359,13 @@ Operations DecisionLogic::FuturePacketAvailable( } bool DecisionLogic::UnderTargetLevel() const { - return buffer_level_filter_->filtered_current_level() <= - delay_manager_->TargetLevel(); + 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(); } bool DecisionLogic::ReinitAfterExpands(uint32_t timestamp_leap) const { diff --git a/modules/audio_coding/neteq/decision_logic.h b/modules/audio_coding/neteq/decision_logic.h index 2414e8cc25..49020b0aab 100644 --- a/modules/audio_coding/neteq/decision_logic.h +++ b/modules/audio_coding/neteq/decision_logic.h @@ -134,9 +134,7 @@ 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(const SyncBuffer& sync_buffer, - const Expand& expand, - size_t decoder_frame_length, + Operations FuturePacketAvailable(size_t decoder_frame_length, Modes prev_mode, uint32_t target_timestamp, uint32_t available_timestamp, diff --git a/modules/audio_coding/neteq/mock/mock_buffer_level_filter.h b/modules/audio_coding/neteq/mock/mock_buffer_level_filter.h index bf9fd59c9a..031195cd0f 100644 --- a/modules/audio_coding/neteq/mock/mock_buffer_level_filter.h +++ b/modules/audio_coding/neteq/mock/mock_buffer_level_filter.h @@ -22,10 +22,8 @@ class MockBufferLevelFilter : public BufferLevelFilter { virtual ~MockBufferLevelFilter() { Die(); } MOCK_METHOD0(Die, void()); MOCK_METHOD0(Reset, void()); - MOCK_METHOD3(Update, - void(size_t buffer_size_packets, - int time_stretched_samples, - size_t packet_len_samples)); + MOCK_METHOD2(Update, + void(size_t buffer_size_samples, int time_stretched_samples)); MOCK_METHOD1(SetTargetBufferLevel, void(int target_buffer_level)); MOCK_CONST_METHOD0(filtered_current_level, int()); }; diff --git a/modules/audio_coding/neteq/neteq_impl.cc b/modules/audio_coding/neteq/neteq_impl.cc index ad6becc90e..82ec18db17 100644 --- a/modules/audio_coding/neteq/neteq_impl.cc +++ b/modules/audio_coding/neteq/neteq_impl.cc @@ -310,18 +310,12 @@ 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, and divide the sum by the sample rate. - const size_t delay_samples = - packet_buffer_samples + sync_buffer_->FutureLength(); + // buffer. + const int delay_samples = buffer_level_filter_->filtered_current_level() + + sync_buffer_->FutureLength(); // The division below will truncate. The return value is in ms. - return static_cast(delay_samples) / rtc::CheckedDivExact(fs_hz_, 1000); + return delay_samples / rtc::CheckedDivExact(fs_hz_, 1000); } int NetEqImpl::NetworkStatistics(NetEqNetworkStatistics* stats) { diff --git a/modules/audio_coding/neteq/neteq_unittest.cc b/modules/audio_coding/neteq/neteq_unittest.cc index 6c67ca8ea0..a8649853e7 100644 --- a/modules/audio_coding/neteq/neteq_unittest.cc +++ b/modules/audio_coding/neteq/neteq_unittest.cc @@ -458,16 +458,16 @@ TEST_F(NetEqDecodingTest, MAYBE_TestBitExactness) { webrtc::test::ResourcePath("audio_coding/neteq_universal_new", "rtp"); const std::string output_checksum = - PlatformChecksum("9652cee1d6771a9cbfda821ae1bbdb41b0dd4dee", - "54a7e32f163663c0af35bf70bf45cefc24ad62ef", "not used", - "9652cee1d6771a9cbfda821ae1bbdb41b0dd4dee", - "79496b0a1ef0a3824f3ee04789748a461bed643f"); + PlatformChecksum("415cc2366810676aad27a92b7a9068e79b7e4093", + "52411c46e946e1d50fa777bbfb4686e7161f9cc7", "not used", + "415cc2366810676aad27a92b7a9068e79b7e4093", + "3e02f268f3b4f3acfcc1c397214ea13d09c212fd"); const std::string network_stats_checksum = - PlatformChecksum("c59b1f9f282b6d8733cdff975e3c150ca4a47d51", - "bca95e565996a4ffd6e2ac15736e08843bdca93b", "not used", - "c59b1f9f282b6d8733cdff975e3c150ca4a47d51", - "c59b1f9f282b6d8733cdff975e3c150ca4a47d51"); + PlatformChecksum("6c8726e8699cc61535e65ef9406d339954a05cf8", + "b9f2c862328ddb8d3ec9e79f61cc1d937ee56df6", "not used", + "6c8726e8699cc61535e65ef9406d339954a05cf8", + "6c8726e8699cc61535e65ef9406d339954a05cf8"); 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|" - "2c05677daa968d6c68b92adf4affb7cd9bb4d363"; + "8884ffe98700454875a88d1c3ea9b55e829a2016"; const std::string output_checksum = PlatformChecksum( - maybe_sse, "b7b7ed802b0e18ee416973bf3b9ae98599b0181d", - "5876e52dda90d5ca433c3726555b907b97c86374", maybe_sse, maybe_sse); + maybe_sse, "1f76c884d16812704dec85f2b98db697108d2d9b", + "f888efef2d0710f202f19ba167ed509609146929", maybe_sse, maybe_sse); const std::string network_stats_checksum = - PlatformChecksum("adb3272498e436d1c019cbfd71610e9510c54497", - "fa935a91abc7291db47428a2d7c5361b98713a92", - "42106aa5267300f709f63737707ef07afd9dac61", - "adb3272498e436d1c019cbfd71610e9510c54497", - "adb3272498e436d1c019cbfd71610e9510c54497"); + PlatformChecksum("bb8d91f71873df562224fe0dc5822b5dfb030090", + "9f858290a675c4ceabf575feb6a59bef76d62eaf", + "12963c965d9d102ebbc1f619508e2960a1f7dbee", + "bb8d91f71873df562224fe0dc5822b5dfb030090", + "bb8d91f71873df562224fe0dc5822b5dfb030090"); 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 = 50; + const int kDelayToleranceMs = 60; const int kMaxTimeToSpeechMs = 200; LongCngWithClockDrift(kDriftFactor, kNetworkFreezeTimeMs, kGetAudioDuringFreezeRecovery, kDelayToleranceMs,