diff --git a/modules/audio_coding/acm2/audio_coding_module_unittest.cc b/modules/audio_coding/acm2/audio_coding_module_unittest.cc index 590dc30f47..4e7493e9d7 100644 --- a/modules/audio_coding/acm2/audio_coding_module_unittest.cc +++ b/modules/audio_coding/acm2/audio_coding_module_unittest.cc @@ -939,58 +939,58 @@ class AcmReceiverBitExactnessOldApi : public ::testing::Test { defined(WEBRTC_CODEC_ILBC) TEST_F(AcmReceiverBitExactnessOldApi, 8kHzOutput) { std::string others_checksum_reference = - GetCPUInfo(kAVX2) != 0 ? "1d7b784031599e2c01a3f575f8439f2f" - : "c119fda4ea2c119ff2a720fd0c289071"; + GetCPUInfo(kAVX2) != 0 ? "6edbfe69b965a8687b8744ed1b8eb5a7" + : "6c204b289486b0695b08a9e94fab1948"; std::string win64_checksum_reference = GetCPUInfo(kAVX2) != 0 ? "405a50f0bcb8827e20aa944299fc59f6" - : "38e70d4e186f8e1a56b929fafcb7c379"; + : "ff5ffee2ee92f8fe61d9f2010b8a68a3"; Run(8000, PlatformChecksum(others_checksum_reference, win64_checksum_reference, - "3b03e41731e1cef5ae2b9f9618660b42", + "53494a96f3db4a5b07d723e0cbac0ad7", "4598140b5e4f7ee66c5adad609e65a3e", - "da7e76687c8c0a9509cd1d57ee1aba3b")); + "516c2859126ea4913f30d51af4a4f3dc")); } TEST_F(AcmReceiverBitExactnessOldApi, 16kHzOutput) { std::string others_checksum_reference = - GetCPUInfo(kAVX2) != 0 ? "8884d910e443c244d8593c2e3cef5e63" - : "36dc8c0532ba0efa099e2b6a689cde40"; + GetCPUInfo(kAVX2) != 0 ? "295f031e051f1770b4ab4107dba768b5" + : "226dbdbce2354399c6df05371042cda3"; std::string win64_checksum_reference = GetCPUInfo(kAVX2) != 0 ? "58fd62a5c49ee513f9fa6fe7dbf62c97" - : "07e4b388168e273fa19da0a167aff782"; + : "9c80bf5ec496c41ce8112e1523bf8c83"; Run(16000, PlatformChecksum(others_checksum_reference, win64_checksum_reference, - "06b08d14a72f6e7c72840b1cc9ad204d", + "11a6f170fdaffa81a2948af121f370af", "f2aad418af974a3b1694d5ae5cc2c3c7", - "1d5f9a93f3975e7e491373b81eb5fd14")); + "6133301a18be95c416984182816d859f")); } TEST_F(AcmReceiverBitExactnessOldApi, 32kHzOutput) { std::string others_checksum_reference = - GetCPUInfo(kAVX2) != 0 ? "73f4fe21996c0af495e2c47e3708e519" - : "c848ce9002d3825056a1eac2a067c0d3"; + GetCPUInfo(kAVX2) != 0 ? "2895e5ab3146eaa78fa6843ed60e7e37" + : "f94665cc0e904d5d5cf0394e30ee4edd"; std::string win64_checksum_reference = GetCPUInfo(kAVX2) != 0 ? "04ce6a1dac5ffdd8438d804623d0132f" - : "0e705f6844c75fd57a84734f7c30af87"; + : "697934bcf0849f80d76ce20854161220"; Run(32000, PlatformChecksum(others_checksum_reference, win64_checksum_reference, - "c18e98e5701ec91bba5c026b720d1790", + "3609aa5288c1d512e8e652ceabecb495", "100869c8dcde51346c2073e52a272d98", - "e35df943bfa3ca32e86b26bf1e37ed8f")); + "55363bc9cdda6464a58044919157827b")); } TEST_F(AcmReceiverBitExactnessOldApi, 48kHzOutput) { std::string others_checksum_reference = - GetCPUInfo(kAVX2) != 0 ? "884243f7e1476931e93eda5de88d1326" - : "ba0f66d538487bba377e721cfac62d1e"; + GetCPUInfo(kAVX2) != 0 ? "640bca210e1b8dd229224d2a0c79ff1f" + : "2955d0b83602541fd92d9b820ebce68d"; std::string win64_checksum_reference = GetCPUInfo(kAVX2) != 0 ? "f59833d9b0924f4b0704707dd3589f80" - : "6a480541fb86faa95c7563b9de08104d"; + : "f4a8386a6a49439ced60ed9a7c7f75fd"; Run(48000, PlatformChecksum(others_checksum_reference, win64_checksum_reference, - "30e617e4b3c9ba1979d1b2e8eba3519b", + "d8169dfeba708b5212bdc365e08aee9d", "bd44bf97e7899186532f91235cef444d", - "90158462a1853b1de50873eebd68dba7")); + "47594deaab5d9166cfbf577203b2563e")); } TEST_F(AcmReceiverBitExactnessOldApi, 48kHzOutputExternalDecoder) { @@ -1069,16 +1069,16 @@ TEST_F(AcmReceiverBitExactnessOldApi, 48kHzOutputExternalDecoder) { rtc::scoped_refptr> factory( new rtc::RefCountedObject); std::string others_checksum_reference = - GetCPUInfo(kAVX2) != 0 ? "884243f7e1476931e93eda5de88d1326" - : "ba0f66d538487bba377e721cfac62d1e"; + GetCPUInfo(kAVX2) != 0 ? "640bca210e1b8dd229224d2a0c79ff1f" + : "2955d0b83602541fd92d9b820ebce68d"; std::string win64_checksum_reference = GetCPUInfo(kAVX2) != 0 ? "f59833d9b0924f4b0704707dd3589f80" - : "6a480541fb86faa95c7563b9de08104d"; + : "f4a8386a6a49439ced60ed9a7c7f75fd"; Run(48000, PlatformChecksum(others_checksum_reference, win64_checksum_reference, - "30e617e4b3c9ba1979d1b2e8eba3519b", + "d8169dfeba708b5212bdc365e08aee9d", "bd44bf97e7899186532f91235cef444d", - "90158462a1853b1de50873eebd68dba7"), + "47594deaab5d9166cfbf577203b2563e"), factory, [](AudioCodingModule* acm) { acm->SetReceiveCodecs({{0, {"MockPCMu", 8000, 1}}, {103, {"ISAC", 16000, 1}}, @@ -1312,11 +1312,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", + "f59760fa000991ee5fa81f2e607db254", + "986aa16d7097a26e32e212e39ec58517", "9a81e467eb1485f84aca796f8ea65011", "ef75e900e6f375e3061163c53fd09a63", - "1ad29139a04782a33daad8c2b9b35875"), + "f59760fa000991ee5fa81f2e607db254"), AcmReceiverBitExactnessOldApi::PlatformChecksum( "9e0a0ab743ad987b55b8e14802769c56", "ebe04a819d3a9d83a83a17f271e1139a", @@ -1349,37 +1349,37 @@ TEST_F(AcmSenderBitExactnessOldApi, MAYBE_IsacSwb30ms) { TEST_F(AcmSenderBitExactnessOldApi, Pcm16_8000khz_10ms) { ASSERT_NO_FATAL_FAILURE(SetUpTest("L16", 8000, 1, 107, 80, 80)); - Run("15396f66b5b0ab6842e151c807395e4c", "c1edd36339ce0326cc4550041ad719a0", + Run("de4a98e1406f8b798d99cd0704e862e2", "c1edd36339ce0326cc4550041ad719a0", 100, test::AcmReceiveTestOldApi::kMonoOutput); } TEST_F(AcmSenderBitExactnessOldApi, Pcm16_16000khz_10ms) { ASSERT_NO_FATAL_FAILURE(SetUpTest("L16", 16000, 1, 108, 160, 160)); - Run("54ae004529874c2b362c7f0ccd19cb99", "ad786526383178b08d80d6eee06e9bad", + Run("ae646d7b68384a1269cc080dd4501916", "ad786526383178b08d80d6eee06e9bad", 100, test::AcmReceiveTestOldApi::kMonoOutput); } TEST_F(AcmSenderBitExactnessOldApi, Pcm16_32000khz_10ms) { ASSERT_NO_FATAL_FAILURE(SetUpTest("L16", 32000, 1, 109, 320, 320)); - Run("d6a4a68b8c838dcc1e7ae7136467cdf0", "5ef82ea885e922263606c6fdbc49f651", + Run("7fe325e8fbaf755e3c5df0b11a4774fb", "5ef82ea885e922263606c6fdbc49f651", 100, test::AcmReceiveTestOldApi::kMonoOutput); } TEST_F(AcmSenderBitExactnessOldApi, Pcm16_stereo_8000khz_10ms) { ASSERT_NO_FATAL_FAILURE(SetUpTest("L16", 8000, 2, 111, 80, 80)); - Run("6b011dab43e3a8a46ccff7e4412ed8a2", "62ce5adb0d4965d0a52ec98ae7f98974", + Run("fb263b74e7ac3de915474d77e4744ceb", "62ce5adb0d4965d0a52ec98ae7f98974", 100, test::AcmReceiveTestOldApi::kStereoOutput); } TEST_F(AcmSenderBitExactnessOldApi, Pcm16_stereo_16000khz_10ms) { ASSERT_NO_FATAL_FAILURE(SetUpTest("L16", 16000, 2, 112, 160, 160)); - Run("17fc9854358bfe0419408290664bd78e", "41ca8edac4b8c71cd54fd9f25ec14870", + Run("d09e9239553649d7ac93e19d304281fd", "41ca8edac4b8c71cd54fd9f25ec14870", 100, test::AcmReceiveTestOldApi::kStereoOutput); } TEST_F(AcmSenderBitExactnessOldApi, Pcm16_stereo_32000khz_10ms) { ASSERT_NO_FATAL_FAILURE(SetUpTest("L16", 32000, 2, 113, 320, 320)); - Run("9ac9a1f64d55da2fc9f3167181cc511d", "50e58502fb04421bf5b857dda4c96879", + Run("5f025d4f390982cc26b3d92fe02e3044", "50e58502fb04421bf5b857dda4c96879", 100, test::AcmReceiveTestOldApi::kStereoOutput); } diff --git a/modules/audio_coding/neteq/buffer_level_filter.cc b/modules/audio_coding/neteq/buffer_level_filter.cc index 7ad006545d..d238665ba2 100644 --- a/modules/audio_coding/neteq/buffer_level_filter.cc +++ b/modules/audio_coding/neteq/buffer_level_filter.cc @@ -45,12 +45,12 @@ void BufferLevelFilter::Update(size_t buffer_size_samples, filtered_current_level - (int64_t{time_stretched_samples} * (1 << 8)))); } -void BufferLevelFilter::SetTargetBufferLevel(int target_buffer_level_ms) { - if (target_buffer_level_ms <= 20) { +void BufferLevelFilter::SetTargetBufferLevel(int target_buffer_level) { + if (target_buffer_level <= 1) { level_factor_ = 251; - } else if (target_buffer_level_ms <= 60) { + } else if (target_buffer_level <= 3) { level_factor_ = 252; - } else if (target_buffer_level_ms <= 140) { + } else if (target_buffer_level <= 7) { level_factor_ = 253; } else { level_factor_ = 254; diff --git a/modules/audio_coding/neteq/buffer_level_filter.h b/modules/audio_coding/neteq/buffer_level_filter.h index bb3185667c..6dd424991b 100644 --- a/modules/audio_coding/neteq/buffer_level_filter.h +++ b/modules/audio_coding/neteq/buffer_level_filter.h @@ -23,13 +23,15 @@ class BufferLevelFilter { virtual ~BufferLevelFilter() {} virtual void Reset(); - // Updates the filter. Current buffer size is |buffer_size_samples|. + // 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); - // The target level is used to select the appropriate filter coefficient. - virtual void SetTargetBufferLevel(int target_buffer_level_ms); + // 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_packets); // Returns filtered current level in number of samples. virtual int filtered_current_level() const { diff --git a/modules/audio_coding/neteq/buffer_level_filter_unittest.cc b/modules/audio_coding/neteq/buffer_level_filter_unittest.cc index 63fc83be67..bc42595cd1 100644 --- a/modules/audio_coding/neteq/buffer_level_filter_unittest.cc +++ b/modules/audio_coding/neteq/buffer_level_filter_unittest.cc @@ -30,7 +30,7 @@ TEST(BufferLevelFilter, ConvergenceTest) { for (int times = 10; times <= 50; times += 10) { for (int value = 100; value <= 200; value += 10) { filter.Reset(); - filter.SetTargetBufferLevel(20); // Makes filter coefficient 251/256. + 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. @@ -57,7 +57,7 @@ TEST(BufferLevelFilter, FilterFactor) { const int kTimes = 10; const int kValue = 100; - filter.SetTargetBufferLevel(60); // Makes filter coefficient 252/256. + filter.SetTargetBufferLevel(3); // Makes filter coefficient 252/256. for (int i = 0; i < kTimes; ++i) { filter.Update(kValue, 0 /* time_stretched_samples */); } @@ -67,7 +67,7 @@ TEST(BufferLevelFilter, FilterFactor) { EXPECT_EQ(expected_value, filter.filtered_current_level()); filter.Reset(); - filter.SetTargetBufferLevel(140); // Makes filter coefficient 253/256. + filter.SetTargetBufferLevel(7); // Makes filter coefficient 253/256. for (int i = 0; i < kTimes; ++i) { filter.Update(kValue, 0 /* time_stretched_samples */); } @@ -77,7 +77,7 @@ TEST(BufferLevelFilter, FilterFactor) { EXPECT_EQ(expected_value, filter.filtered_current_level()); filter.Reset(); - filter.SetTargetBufferLevel(160); // Makes filter coefficient 254/256. + filter.SetTargetBufferLevel(8); // Makes filter coefficient 254/256. for (int i = 0; i < kTimes; ++i) { filter.Update(kValue, 0 /* time_stretched_samples */); } @@ -89,7 +89,7 @@ TEST(BufferLevelFilter, FilterFactor) { TEST(BufferLevelFilter, TimeStretchedSamples) { BufferLevelFilter filter; - filter.SetTargetBufferLevel(20); // Makes filter coefficient 251/256. + filter.SetTargetBufferLevel(1); // Makes filter coefficient 251/256. // Update 10 times with value 100. const int kTimes = 10; const int kValue = 100; diff --git a/modules/audio_coding/neteq/decision_logic.cc b/modules/audio_coding/neteq/decision_logic.cc index a4de9b8bb4..8e1ffaf9fe 100644 --- a/modules/audio_coding/neteq/decision_logic.cc +++ b/modules/audio_coding/neteq/decision_logic.cc @@ -27,7 +27,6 @@ namespace { constexpr int kPostponeDecodingLevel = 50; constexpr int kDefaultTargetLevelWindowMs = 100; -constexpr int kDecelerationTargetLevelOffsetMs = 85; } // namespace @@ -36,6 +35,7 @@ namespace webrtc { DecisionLogic::DecisionLogic(NetEqController::Config config) : delay_manager_(DelayManager::Create(config.max_packets_in_buffer, config.base_min_delay_ms, + config.enable_rtx_handling, config.tick_timer)), tick_timer_(config.tick_timer), disallow_time_stretching_(!config.allow_time_stretching), @@ -67,7 +67,6 @@ void DecisionLogic::Reset() { packet_length_samples_ = 0; sample_memory_ = 0; prev_time_scale_ = false; - last_pack_cng_or_dtmf_ = true; timescale_countdown_.reset(); num_consecutive_expands_ = 0; time_stretched_cn_samples_ = 0; @@ -77,7 +76,6 @@ void DecisionLogic::SoftReset() { packet_length_samples_ = 0; sample_memory_ = 0; prev_time_scale_ = false; - last_pack_cng_or_dtmf_ = true; timescale_countdown_ = tick_timer_->GetNewCountdown(kMinTimescaleInterval + 1); time_stretched_cn_samples_ = 0; @@ -160,13 +158,12 @@ NetEq::Operation DecisionLogic::GetDecision(const NetEqStatus& status, const size_t current_span = estimate_dtx_delay_ ? status.packet_buffer_info.span_samples : status.packet_buffer_info.span_samples_no_dtx; - const int target_level_samples = - delay_manager_->TargetDelayMs() * sample_rate_ / 1000; if ((status.last_mode == NetEq::Mode::kExpand || status.last_mode == NetEq::Mode::kCodecPlc) && status.expand_mutefactor < 16384 / 2 && - current_span < static_cast(target_level_samples * - kPostponeDecodingLevel / 100) && + current_span(delay_manager_->TargetLevel() * + packet_length_samples_ * + kPostponeDecodingLevel / 100)>> 8 && !status.packet_buffer_info.dtx_or_cng) { return NetEq::Operation::kExpand; } @@ -198,32 +195,41 @@ void DecisionLogic::ExpandDecision(NetEq::Operation operation) { } } -absl::optional DecisionLogic::PacketArrived(bool is_cng_or_dtmf, +absl::optional DecisionLogic::PacketArrived(bool last_cng_or_dtmf, size_t packet_length_samples, bool should_update_stats, uint16_t main_sequence_number, uint32_t main_timestamp, int fs_hz) { - if (is_cng_or_dtmf) { - last_pack_cng_or_dtmf_ = true; - return absl::nullopt; + delay_manager_->LastDecodedWasCngOrDtmf(last_cng_or_dtmf); + absl::optional relative_delay; + if (delay_manager_->last_pack_cng_or_dtmf() == 0) { + // Calculate the total speech length carried in each packet. + if (packet_length_samples > 0 && + packet_length_samples != packet_length_samples_) { + packet_length_samples_ = packet_length_samples; + delay_manager_->SetPacketAudioLength( + rtc::dchecked_cast((1000 * packet_length_samples) / fs_hz)); + } + + // Update statistics. + if (should_update_stats) { + relative_delay = + delay_manager_->Update(main_sequence_number, main_timestamp, fs_hz); + } + } else if (delay_manager_->last_pack_cng_or_dtmf() == -1) { + // This is first "normal" packet after CNG or DTMF. + // Reset packet time counter and measure time until next packet, + // but don't update statistics. + delay_manager_->set_last_pack_cng_or_dtmf(0); + delay_manager_->ResetPacketIatCount(); } - if (!should_update_stats) { - return absl::nullopt; - } - if (packet_length_samples > 0 && fs_hz > 0 && - packet_length_samples != packet_length_samples_) { - packet_length_samples_ = packet_length_samples; - delay_manager_->SetPacketAudioLength(packet_length_samples_ * 1000 / fs_hz); - } - auto relative_delay = delay_manager_->Update( - main_timestamp, fs_hz, /*reset=*/last_pack_cng_or_dtmf_); - last_pack_cng_or_dtmf_ = false; return relative_delay; } void DecisionLogic::FilterBufferLevel(size_t buffer_size_samples) { - buffer_level_filter_.SetTargetBufferLevel(delay_manager_->TargetDelayMs()); + buffer_level_filter_.SetTargetBufferLevel( + delay_manager_->base_target_level()); int time_stretched_samples = time_stretched_cn_samples_; if (prev_time_scale_) { @@ -244,8 +250,8 @@ NetEq::Operation DecisionLogic::CngOperation(NetEq::Mode prev_mode, int32_t timestamp_diff = static_cast( static_cast(generated_noise_samples + target_timestamp) - available_timestamp); - int optimal_level_samp = - delay_manager_->TargetDelayMs() * sample_rate_ / 1000; + int32_t optimal_level_samp = static_cast( + (delay_manager_->TargetLevel() * packet_length_samples_) >> 8); const int64_t excess_waiting_time_samp = -static_cast(timestamp_diff) - optimal_level_samp; @@ -289,26 +295,22 @@ NetEq::Operation DecisionLogic::ExpectedPacketAvailable(NetEq::Mode prev_mode, bool play_dtmf) { if (!disallow_time_stretching_ && prev_mode != NetEq::Mode::kExpand && !play_dtmf) { - const int samples_per_ms = sample_rate_ / 1000; - const int target_level_samples = - delay_manager_->TargetDelayMs() * samples_per_ms; - const int low_limit = - std::max(target_level_samples * 3 / 4, - target_level_samples - - kDecelerationTargetLevelOffsetMs * samples_per_ms); - // |higher_limit| is equal to |target_level|, but should at - // least be 20 ms higher than |lower_limit|. - const int high_limit = - std::max(target_level_samples, low_limit + 20 * samples_per_ms); - - const int buffer_level_samples = - buffer_level_filter_.filtered_current_level(); - if (buffer_level_samples >= high_limit << 2) + // 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); + 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 NetEq::Operation::kFastAccelerate; if (TimescaleAllowed()) { - if (buffer_level_samples >= high_limit) + if (buffer_level_packets >= high_limit) return NetEq::Operation::kAccelerate; - if (buffer_level_samples < low_limit) + if (buffer_level_packets < low_limit) return NetEq::Operation::kPreemptiveExpand; } } @@ -350,11 +352,11 @@ NetEq::Operation DecisionLogic::FuturePacketAvailable( prev_mode == NetEq::Mode::kCodecInternalCng) { size_t cur_size_samples = estimate_dtx_delay_ - ? span_samples_in_packet_buffer + ? cur_size_samples = span_samples_in_packet_buffer : num_packets_in_packet_buffer * decoder_frame_length; // Target level is in number of packets in Q8. const size_t target_level_samples = - delay_manager_->TargetDelayMs() * sample_rate_ / 1000; + (delay_manager_->TargetLevel() * packet_length_samples_) >> 8; const bool generated_enough_noise = static_cast(generated_noise_samples + target_timestamp) >= available_timestamp; @@ -404,8 +406,13 @@ NetEq::Operation DecisionLogic::FuturePacketAvailable( } bool DecisionLogic::UnderTargetLevel() const { - return buffer_level_filter_.filtered_current_level() < - delay_manager_->TargetDelayMs() * sample_rate_ / 1000; + 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 d4d69edb04..c3d82eb52f 100644 --- a/modules/audio_coding/neteq/decision_logic.h +++ b/modules/audio_coding/neteq/decision_logic.h @@ -70,16 +70,19 @@ class DecisionLogic : public NetEqController { // Adds |value| to |sample_memory_|. void AddSampleMemory(int32_t value) override { sample_memory_ += value; } - int TargetLevelMs() const override { return delay_manager_->TargetDelayMs(); } + int TargetLevelMs() const override { + return ((delay_manager_->TargetLevel() * packet_length_samples_) >> 8) / + rtc::CheckedDivExact(sample_rate_, 1000); + } - absl::optional PacketArrived(bool is_cng_or_dtmf, + absl::optional PacketArrived(bool last_cng_or_dtmf, size_t packet_length_samples, bool should_update_stats, uint16_t main_sequence_number, uint32_t main_timestamp, int fs_hz) override; - void RegisterEmptyPacket() override {} + void RegisterEmptyPacket() override { delay_manager_->RegisterEmptyPacket(); } void NotifyMutedState() override {} @@ -119,8 +122,8 @@ class DecisionLogic : public NetEqController { enum CngState { kCngOff, kCngRfc3389On, kCngInternalOn }; // Updates the |buffer_level_filter_| with the current buffer level - // |buffer_size_samples|. - void FilterBufferLevel(size_t buffer_size_samples); + // |buffer_size_packets|. + void FilterBufferLevel(size_t buffer_size_packets); // Returns the operation given that the next available packet is a comfort // noise payload (RFC 3389 only, not codec-internal). @@ -185,7 +188,6 @@ class DecisionLogic : public NetEqController { std::unique_ptr timescale_countdown_; int num_consecutive_expands_ = 0; int time_stretched_cn_samples_ = 0; - bool last_pack_cng_or_dtmf_ = true; FieldTrialParameter estimate_dtx_delay_; FieldTrialParameter time_stretch_cn_; FieldTrialConstrained target_level_window_ms_; diff --git a/modules/audio_coding/neteq/decision_logic_unittest.cc b/modules/audio_coding/neteq/decision_logic_unittest.cc index 56e8b84722..a5b6712e73 100644 --- a/modules/audio_coding/neteq/decision_logic_unittest.cc +++ b/modules/audio_coding/neteq/decision_logic_unittest.cc @@ -43,6 +43,6 @@ TEST(DecisionLogic, CreateAndDestroy) { logic->SetSampleRate(fs_hz, output_size_samples); } -// TODO(jakobi): Write more tests. +// TODO(hlundin): Write more tests. } // namespace webrtc diff --git a/modules/audio_coding/neteq/delay_manager.cc b/modules/audio_coding/neteq/delay_manager.cc index 5b541867a3..4ae6d108cb 100644 --- a/modules/audio_coding/neteq/delay_manager.cc +++ b/modules/audio_coding/neteq/delay_manager.cc @@ -27,16 +27,17 @@ #include "rtc_base/numerics/safe_minmax.h" #include "system_wrappers/include/field_trial.h" -namespace webrtc { namespace { constexpr int kMinBaseMinimumDelayMs = 0; constexpr int kMaxBaseMinimumDelayMs = 10000; +constexpr int kMaxReorderedPackets = + 10; // Max number of consecutive reordered packets. constexpr int kMaxHistoryMs = 2000; // Oldest packet to include in history to // calculate relative packet arrival delay. constexpr int kDelayBuckets = 100; constexpr int kBucketSizeMs = 20; -constexpr int kStartDelayMs = 80; +constexpr int kDecelerationTargetLevelOffsetMs = 85 << 8; // In Q8. int PercentileToQuantile(double percentile) { return static_cast((1 << 30) * percentile / 100.0 + 0.5); @@ -48,7 +49,6 @@ struct DelayHistogramConfig { absl::optional start_forget_weight = 2; }; -// TODO(jakobi): Remove legacy field trial. DelayHistogramConfig GetDelayHistogramConfig() { constexpr char kDelayHistogramFieldTrial[] = "WebRTC-Audio-NetEqDelayHistogram"; @@ -81,9 +81,12 @@ DelayHistogramConfig GetDelayHistogramConfig() { } // namespace -DelayManager::DelayManager(int max_packets_in_buffer, +namespace webrtc { + +DelayManager::DelayManager(size_t max_packets_in_buffer, int base_minimum_delay_ms, int histogram_quantile, + bool enable_rtx_handling, const TickTimer* tick_timer, std::unique_ptr histogram) : first_packet_received_(false), @@ -93,10 +96,15 @@ DelayManager::DelayManager(int max_packets_in_buffer, tick_timer_(tick_timer), base_minimum_delay_ms_(base_minimum_delay_ms), effective_minimum_delay_ms_(base_minimum_delay_ms), + base_target_level_(4), // In Q0 domain. + target_level_(base_target_level_ << 8), // In Q8 domain. + packet_len_ms_(0), + last_seq_no_(0), + last_timestamp_(0), minimum_delay_ms_(0), maximum_delay_ms_(0), - target_level_ms_(kStartDelayMs), - last_timestamp_(0) { + last_pack_cng_or_dtmf_(1), + enable_rtx_handling_(enable_rtx_handling) { RTC_CHECK(histogram_); RTC_DCHECK_GE(base_minimum_delay_ms_, 0); @@ -104,70 +112,102 @@ DelayManager::DelayManager(int max_packets_in_buffer, } std::unique_ptr DelayManager::Create( - int max_packets_in_buffer, + size_t max_packets_in_buffer, int base_minimum_delay_ms, + bool enable_rtx_handling, const TickTimer* tick_timer) { - auto config = GetDelayHistogramConfig(); + DelayHistogramConfig config = GetDelayHistogramConfig(); + const int quantile = config.quantile; std::unique_ptr histogram = std::make_unique( kDelayBuckets, config.forget_factor, config.start_forget_weight); - return std::make_unique(max_packets_in_buffer, - base_minimum_delay_ms, config.quantile, - tick_timer, std::move(histogram)); + return std::make_unique( + max_packets_in_buffer, base_minimum_delay_ms, quantile, + enable_rtx_handling, tick_timer, std::move(histogram)); } DelayManager::~DelayManager() {} -absl::optional DelayManager::Update(uint32_t timestamp, - int sample_rate_hz, - bool reset) { +absl::optional DelayManager::Update(uint16_t sequence_number, + uint32_t timestamp, + int sample_rate_hz) { if (sample_rate_hz <= 0) { return absl::nullopt; } - if (!first_packet_received_ || reset) { - // Restart relative delay esimation from this packet. - delay_history_.clear(); + if (!first_packet_received_) { + // Prepare for next packet arrival. packet_iat_stopwatch_ = tick_timer_->GetNewStopwatch(); + last_seq_no_ = sequence_number; last_timestamp_ = timestamp; first_packet_received_ = true; return absl::nullopt; } - const int expected_iat_ms = - 1000 * static_cast(timestamp - last_timestamp_) / sample_rate_hz; - const int iat_ms = packet_iat_stopwatch_->ElapsedMs(); - const int iat_delay_ms = iat_ms - expected_iat_ms; - absl::optional relative_delay; - if (!IsNewerTimestamp(timestamp, last_timestamp_)) { - relative_delay = std::max(iat_delay_ms, 0); - // Reset the history and restart delay estimation from this packet. - delay_history_.clear(); + // Try calculating packet length from current and previous timestamps. + int packet_len_ms; + if (!IsNewerTimestamp(timestamp, last_timestamp_) || + !IsNewerSequenceNumber(sequence_number, last_seq_no_)) { + // Wrong timestamp or sequence order; use stored value. + packet_len_ms = packet_len_ms_; } else { - UpdateDelayHistory(iat_delay_ms, timestamp, sample_rate_hz); - relative_delay = CalculateRelativePacketArrivalDelay(); - } - const int index = relative_delay.value() / kBucketSizeMs; - if (index < histogram_->NumBuckets()) { - // Maximum delay to register is 2000 ms. - histogram_->Add(index); - } - // Calculate new |target_level_ms_| based on updated statistics. - int bucket_index = histogram_->Quantile(histogram_quantile_); - target_level_ms_ = (1 + bucket_index) * kBucketSizeMs; - target_level_ms_ = std::max(target_level_ms_, effective_minimum_delay_ms_); - if (maximum_delay_ms_ > 0) { - target_level_ms_ = std::min(target_level_ms_, maximum_delay_ms_); - } - if (packet_len_ms_ > 0) { - // Target level should be at least one packet. - target_level_ms_ = std::max(target_level_ms_, packet_len_ms_); - // Limit to 75% of maximum buffer size. - target_level_ms_ = std::min( - target_level_ms_, 3 * max_packets_in_buffer_ * packet_len_ms_ / 4); + // Calculate timestamps per packet and derive packet length in ms. + int64_t packet_len_samp = + static_cast(timestamp - last_timestamp_) / + static_cast(sequence_number - last_seq_no_); + packet_len_ms = + rtc::saturated_cast(1000 * packet_len_samp / sample_rate_hz); } + bool reordered = false; + absl::optional relative_delay; + if (packet_len_ms > 0) { + // Cannot update statistics unless |packet_len_ms| is valid. + + // Inter-arrival time (IAT) in integer "packet times" (rounding down). This + // is the value added to the inter-arrival time histogram. + int iat_ms = packet_iat_stopwatch_->ElapsedMs(); + // Check for discontinuous packet sequence and re-ordering. + if (IsNewerSequenceNumber(sequence_number, last_seq_no_ + 1)) { + // Compensate for gap in the sequence numbers. Reduce IAT with the + // expected extra time due to lost packets. + int packet_offset = + static_cast(sequence_number - last_seq_no_ - 1); + iat_ms -= packet_offset * packet_len_ms; + } else if (!IsNewerSequenceNumber(sequence_number, last_seq_no_)) { + int packet_offset = + static_cast(last_seq_no_ + 1 - sequence_number); + iat_ms += packet_offset * packet_len_ms; + reordered = true; + } + + int iat_delay = iat_ms - packet_len_ms; + if (reordered) { + relative_delay = std::max(iat_delay, 0); + } else { + UpdateDelayHistory(iat_delay, timestamp, sample_rate_hz); + relative_delay = CalculateRelativePacketArrivalDelay(); + } + + const int index = relative_delay.value() / kBucketSizeMs; + if (index < histogram_->NumBuckets()) { + // Maximum delay to register is 2000 ms. + histogram_->Add(index); + } + // Calculate new |target_level_| based on updated statistics. + target_level_ = CalculateTargetLevel(); + + LimitTargetLevel(); + } // End if (packet_len_ms > 0). + + if (enable_rtx_handling_ && reordered && + num_reordered_packets_ < kMaxReorderedPackets) { + ++num_reordered_packets_; + return relative_delay; + } + num_reordered_packets_ = 0; // Prepare for next packet arrival. packet_iat_stopwatch_ = tick_timer_->GetNewStopwatch(); + last_seq_no_ = sequence_number; last_timestamp_ = timestamp; return relative_delay; } @@ -198,26 +238,128 @@ int DelayManager::CalculateRelativePacketArrivalDelay() const { return relative_delay; } +// Enforces upper and lower limits for |target_level_|. The upper limit is +// chosen to be minimum of i) 75% of |max_packets_in_buffer_|, to leave some +// headroom for natural fluctuations around the target, and ii) equivalent of +// |maximum_delay_ms_| in packets. Note that in practice, if no +// |maximum_delay_ms_| is specified, this does not have any impact, since the +// target level is far below the buffer capacity in all reasonable cases. +// The lower limit is equivalent of |effective_minimum_delay_ms_| in packets. +// We update |least_required_level_| while the above limits are applied. +// TODO(hlundin): Move this check to the buffer logistics class. +void DelayManager::LimitTargetLevel() { + if (packet_len_ms_ > 0 && effective_minimum_delay_ms_ > 0) { + int minimum_delay_packet_q8 = + (effective_minimum_delay_ms_ << 8) / packet_len_ms_; + target_level_ = std::max(target_level_, minimum_delay_packet_q8); + } + + if (maximum_delay_ms_ > 0 && packet_len_ms_ > 0) { + int maximum_delay_packet_q8 = (maximum_delay_ms_ << 8) / packet_len_ms_; + target_level_ = std::min(target_level_, maximum_delay_packet_q8); + } + + // Shift to Q8, then 75%.; + int max_buffer_packets_q8 = + static_cast((3 * (max_packets_in_buffer_ << 8)) / 4); + target_level_ = std::min(target_level_, max_buffer_packets_q8); + + // Sanity check, at least 1 packet (in Q8). + target_level_ = std::max(target_level_, 1 << 8); +} + +int DelayManager::CalculateTargetLevel() { + int limit_probability = histogram_quantile_; + + int bucket_index = histogram_->Quantile(limit_probability); + int target_level = 1; + if (packet_len_ms_ > 0) { + target_level += bucket_index * kBucketSizeMs / packet_len_ms_; + } + base_target_level_ = target_level; + + // Sanity check. |target_level| must be strictly positive. + target_level = std::max(target_level, 1); + // Scale to Q8 and assign to member variable. + target_level_ = target_level << 8; + return target_level_; +} + int DelayManager::SetPacketAudioLength(int length_ms) { if (length_ms <= 0) { RTC_LOG_F(LS_ERROR) << "length_ms = " << length_ms; return -1; } + packet_len_ms_ = length_ms; + packet_iat_stopwatch_ = tick_timer_->GetNewStopwatch(); + last_pack_cng_or_dtmf_ = 1; // TODO(hlundin): Legacy. Remove? return 0; } void DelayManager::Reset() { - packet_len_ms_ = 0; + packet_len_ms_ = 0; // Packet size unknown. histogram_->Reset(); delay_history_.clear(); - target_level_ms_ = kStartDelayMs; + base_target_level_ = 4; + target_level_ = base_target_level_ << 8; packet_iat_stopwatch_ = tick_timer_->GetNewStopwatch(); - first_packet_received_ = false; + last_pack_cng_or_dtmf_ = 1; } -int DelayManager::TargetDelayMs() const { - return target_level_ms_; +void DelayManager::ResetPacketIatCount() { + packet_iat_stopwatch_ = tick_timer_->GetNewStopwatch(); +} + +void DelayManager::BufferLimits(int* lower_limit, int* higher_limit) const { + BufferLimits(target_level_, lower_limit, higher_limit); +} + +// Note that |low_limit| and |higher_limit| are not assigned to +// |minimum_delay_ms_| and |maximum_delay_ms_| defined by the client of this +// class. They are computed from |target_level| in Q8 and used for decision +// making. +void DelayManager::BufferLimits(int target_level, + int* lower_limit, + int* higher_limit) const { + if (!lower_limit || !higher_limit) { + RTC_LOG_F(LS_ERROR) << "NULL pointers supplied as input"; + assert(false); + return; + } + + // |target_level| is in Q8 already. + *lower_limit = (target_level * 3) / 4; + + if (packet_len_ms_ > 0) { + *lower_limit = + std::max(*lower_limit, target_level - kDecelerationTargetLevelOffsetMs / + packet_len_ms_); + } + + int window_20ms = 0x7FFF; // Default large value for legacy bit-exactness. + if (packet_len_ms_ > 0) { + window_20ms = (20 << 8) / packet_len_ms_; + } + // |higher_limit| is equal to |target_level|, but should at + // least be 20 ms higher than |lower_limit|. + *higher_limit = std::max(target_level, *lower_limit + window_20ms); +} + +int DelayManager::TargetLevel() const { + return target_level_; +} + +void DelayManager::LastDecodedWasCngOrDtmf(bool it_was) { + if (it_was) { + last_pack_cng_or_dtmf_ = 1; + } else if (last_pack_cng_or_dtmf_ != 0) { + last_pack_cng_or_dtmf_ = -1; + } +} + +void DelayManager::RegisterEmptyPacket() { + ++last_seq_no_; } bool DelayManager::IsValidMinimumDelay(int delay_ms) const { @@ -267,6 +409,17 @@ int DelayManager::GetBaseMinimumDelay() const { return base_minimum_delay_ms_; } +int DelayManager::base_target_level() const { + return base_target_level_; +} +int DelayManager::last_pack_cng_or_dtmf() const { + return last_pack_cng_or_dtmf_; +} + +void DelayManager::set_last_pack_cng_or_dtmf(int value) { + last_pack_cng_or_dtmf_ = value; +} + void DelayManager::UpdateEffectiveMinimumDelay() { // Clamp |base_minimum_delay_ms_| into the range which can be effectively // used. @@ -279,11 +432,16 @@ void DelayManager::UpdateEffectiveMinimumDelay() { int DelayManager::MinimumDelayUpperBound() const { // Choose the lowest possible bound discarding 0 cases which mean the value // is not set and unconstrained. - int q75 = max_packets_in_buffer_ * packet_len_ms_ * 3 / 4; + int q75 = MaxBufferTimeQ75(); q75 = q75 > 0 ? q75 : kMaxBaseMinimumDelayMs; const int maximum_delay_ms = maximum_delay_ms_ > 0 ? maximum_delay_ms_ : kMaxBaseMinimumDelayMs; return std::min(maximum_delay_ms, q75); } +int DelayManager::MaxBufferTimeQ75() const { + const int max_buffer_time = max_packets_in_buffer_ * packet_len_ms_; + return rtc::dchecked_cast(3 * max_buffer_time / 4); +} + } // namespace webrtc diff --git a/modules/audio_coding/neteq/delay_manager.h b/modules/audio_coding/neteq/delay_manager.h index d503e0239f..ab9ba34167 100644 --- a/modules/audio_coding/neteq/delay_manager.h +++ b/modules/audio_coding/neteq/delay_manager.h @@ -25,9 +25,10 @@ namespace webrtc { class DelayManager { public: - DelayManager(int max_packets_in_buffer, + DelayManager(size_t max_packets_in_buffer, int base_minimum_delay_ms, int histogram_quantile, + bool enable_rtx_handling, const TickTimer* tick_timer, std::unique_ptr histogram); @@ -36,41 +37,75 @@ class DelayManager { // is the number of packet slots in the buffer) and that the target delay // should be greater than or equal to |base_minimum_delay_ms|. Supply a // PeakDetector object to the DelayManager. - static std::unique_ptr Create(int max_packets_in_buffer, + static std::unique_ptr Create(size_t max_packets_in_buffer, int base_minimum_delay_ms, + bool enable_rtx_handling, const TickTimer* tick_timer); virtual ~DelayManager(); - // Updates the delay manager with a new incoming packet, with |timestamp| from - // the RTP header. This updates the statistics and a new target buffer level - // is calculated. Returns the relative delay if it can be calculated. If - // |reset| is true, restarts the relative arrival delay calculation from this - // packet. - virtual absl::optional Update(uint32_t timestamp, - int sample_rate_hz, - bool reset = false); + // Updates the delay manager with a new incoming packet, with + // |sequence_number| and |timestamp| from the RTP header. This updates the + // inter-arrival time histogram and other statistics, as well as the + // associated DelayPeakDetector. A new target buffer level is calculated. + // Returns the relative delay if it can be calculated. + virtual absl::optional Update(uint16_t sequence_number, + uint32_t timestamp, + int sample_rate_hz); - // Resets all state. - virtual void Reset(); - - // Gets the target buffer level in milliseconds. - virtual int TargetDelayMs() const; + // Calculates a new target buffer level. Called from the Update() method. + // Sets target_level_ (in Q8) and returns the same value. Also calculates + // and updates base_target_level_, which is the target buffer level before + // taking delay peaks into account. + virtual int CalculateTargetLevel(); // Notifies the DelayManager of how much audio data is carried in each packet. + // The method updates the DelayPeakDetector too, and resets the inter-arrival + // time counter. Returns 0 on success, -1 on failure. virtual int SetPacketAudioLength(int length_ms); + // Resets the DelayManager and the associated DelayPeakDetector. + virtual void Reset(); + + // Reset the inter-arrival time counter to 0. + virtual void ResetPacketIatCount(); + + // Writes the lower and higher limits which the buffer level should stay + // within to the corresponding pointers. The values are in (fractions of) + // packets in Q8. + virtual void BufferLimits(int* lower_limit, int* higher_limit) const; + virtual void BufferLimits(int target_level, + int* lower_limit, + int* higher_limit) const; + + // Gets the target buffer level, in (fractions of) packets in Q8. + virtual int TargetLevel() const; + + // Informs the delay manager whether or not the last decoded packet contained + // speech. + virtual void LastDecodedWasCngOrDtmf(bool it_was); + + // Notify the delay manager that empty packets have been received. These are + // packets that are part of the sequence number series, so that an empty + // packet will shift the sequence numbers for the following packets. + virtual void RegisterEmptyPacket(); + // Accessors and mutators. // Assuming |delay| is in valid range. virtual bool SetMinimumDelay(int delay_ms); virtual bool SetMaximumDelay(int delay_ms); virtual bool SetBaseMinimumDelay(int delay_ms); virtual int GetBaseMinimumDelay() const; + virtual int base_target_level() const; + virtual int last_pack_cng_or_dtmf() const; + virtual void set_last_pack_cng_or_dtmf(int value); - // These accessors are only intended for testing purposes. + // This accessor is only intended for testing purposes. int effective_minimum_delay_ms_for_test() const { return effective_minimum_delay_ms_; } + + // These accessors are only intended for testing purposes. int histogram_quantile() const { return histogram_quantile_; } Histogram* histogram() const { return histogram_.get(); } @@ -79,6 +114,9 @@ class DelayManager { // size and given |maximum_delay_ms_|. Lower bound is a constant 0. int MinimumDelayUpperBound() const; + // Provides 75% of currently possible maximum buffer size in milliseconds. + int MaxBufferTimeQ75() const; + // Updates |delay_history_|. void UpdateDelayHistory(int iat_delay_ms, uint32_t timestamp, @@ -92,6 +130,10 @@ class DelayManager { // and buffer size. void UpdateEffectiveMinimumDelay(); + // Makes sure that |target_level_| is not too large, taking + // |max_packets_in_buffer_| into account. This method is called by Update(). + void LimitTargetLevel(); + // Makes sure that |delay_ms| is less than maximum delay, if any maximum // is set. Also, if possible check |delay_ms| to be less than 75% of // |max_packets_in_buffer_|. @@ -100,21 +142,31 @@ class DelayManager { bool IsValidBaseMinimumDelay(int delay_ms) const; bool first_packet_received_; - // TODO(jakobi): set maximum buffer delay instead of number of packets. - const int max_packets_in_buffer_; + const size_t max_packets_in_buffer_; // Capacity of the packet buffer. std::unique_ptr histogram_; const int histogram_quantile_; const TickTimer* tick_timer_; int base_minimum_delay_ms_; - int effective_minimum_delay_ms_; // Used as lower bound for target delay. - int minimum_delay_ms_; // Externally set minimum delay. - int maximum_delay_ms_; // Externally set maximum allowed delay. + // Provides delay which is used by LimitTargetLevel as lower bound on target + // delay. + int effective_minimum_delay_ms_; - int packet_len_ms_ = 0; - std::unique_ptr - packet_iat_stopwatch_; // Time elapsed since last packet. - int target_level_ms_; // Currently preferred buffer level. - uint32_t last_timestamp_; // Timestamp for the last received packet. + // Time elapsed since last packet. + std::unique_ptr packet_iat_stopwatch_; + int base_target_level_; // Currently preferred buffer level before peak + // detection and streaming mode (Q0). + // TODO(turajs) change the comment according to the implementation of + // minimum-delay. + int target_level_; // Currently preferred buffer level in (fractions) + // of packets (Q8), before adding any extra delay. + int packet_len_ms_; // Length of audio in each incoming packet [ms]. + uint16_t last_seq_no_; // Sequence number for last received packet. + uint32_t last_timestamp_; // Timestamp for the last received packet. + int minimum_delay_ms_; // Externally set minimum delay. + int maximum_delay_ms_; // Externally set maximum allowed delay. + int last_pack_cng_or_dtmf_; + const bool enable_rtx_handling_; + int num_reordered_packets_ = 0; // Number of consecutive reordered packets. struct PacketDelay { int iat_delay_ms; diff --git a/modules/audio_coding/neteq/delay_manager_unittest.cc b/modules/audio_coding/neteq/delay_manager_unittest.cc index 50939461f1..4a118f765f 100644 --- a/modules/audio_coding/neteq/delay_manager_unittest.cc +++ b/modules/audio_coding/neteq/delay_manager_unittest.cc @@ -35,15 +35,19 @@ constexpr int kFrameSizeMs = 20; constexpr int kTsIncrement = kFrameSizeMs * kFs / 1000; constexpr int kMaxBufferSizeMs = kMaxNumberOfPackets * kFrameSizeMs; constexpr int kDefaultHistogramQuantile = 1020054733; -constexpr int kNumBuckets = 100; +constexpr int kMaxIat = 64; constexpr int kForgetFactor = 32745; } // namespace +using ::testing::_; +using ::testing::Return; + class DelayManagerTest : public ::testing::Test { protected: DelayManagerTest(); virtual void SetUp(); void RecreateDelayManager(); + void SetPacketAudioLength(int lengt_ms); absl::optional InsertNextPacket(); void IncreaseTime(int inc_ms); @@ -51,12 +55,15 @@ class DelayManagerTest : public ::testing::Test { TickTimer tick_timer_; MockStatisticsCalculator stats_; MockHistogram* mock_histogram_; + uint16_t seq_no_; uint32_t ts_; + bool enable_rtx_handling_ = false; bool use_mock_histogram_ = false; }; DelayManagerTest::DelayManagerTest() : dm_(nullptr), + seq_no_(0x1234), ts_(0x12345678) {} void DelayManagerTest::SetUp() { @@ -65,19 +72,24 @@ void DelayManagerTest::SetUp() { void DelayManagerTest::RecreateDelayManager() { if (use_mock_histogram_) { - mock_histogram_ = new MockHistogram(kNumBuckets, kForgetFactor); + mock_histogram_ = new MockHistogram(kMaxIat, kForgetFactor); std::unique_ptr histogram(mock_histogram_); - dm_ = std::make_unique(kMaxNumberOfPackets, kMinDelayMs, - kDefaultHistogramQuantile, - &tick_timer_, std::move(histogram)); + dm_ = std::make_unique( + kMaxNumberOfPackets, kMinDelayMs, kDefaultHistogramQuantile, + enable_rtx_handling_, &tick_timer_, std::move(histogram)); } else { - dm_ = DelayManager::Create(kMaxNumberOfPackets, kMinDelayMs, &tick_timer_); + dm_ = DelayManager::Create(kMaxNumberOfPackets, kMinDelayMs, + enable_rtx_handling_, &tick_timer_); } - dm_->SetPacketAudioLength(kFrameSizeMs); +} + +void DelayManagerTest::SetPacketAudioLength(int lengt_ms) { + dm_->SetPacketAudioLength(lengt_ms); } absl::optional DelayManagerTest::InsertNextPacket() { - auto relative_delay = dm_->Update(ts_, kFs); + auto relative_delay = dm_->Update(seq_no_, ts_, kFs); + seq_no_ += 1; ts_ += kTsIncrement; return relative_delay; } @@ -93,66 +105,98 @@ TEST_F(DelayManagerTest, CreateAndDestroy) { // object. } +TEST_F(DelayManagerTest, SetPacketAudioLength) { + const int kLengthMs = 30; + EXPECT_EQ(0, dm_->SetPacketAudioLength(kLengthMs)); + EXPECT_EQ(-1, dm_->SetPacketAudioLength(-1)); // Illegal parameter value. +} + TEST_F(DelayManagerTest, UpdateNormal) { + SetPacketAudioLength(kFrameSizeMs); // First packet arrival. InsertNextPacket(); // Advance time by one frame size. IncreaseTime(kFrameSizeMs); // Second packet arrival. InsertNextPacket(); - EXPECT_EQ(20, dm_->TargetDelayMs()); + EXPECT_EQ(1 << 8, dm_->TargetLevel()); // In Q8. + EXPECT_EQ(1, dm_->base_target_level()); + int lower, higher; + dm_->BufferLimits(&lower, &higher); + // Expect |lower| to be 75% of target level, and |higher| to be target level, + // but also at least 20 ms higher than |lower|, which is the limiting case + // here. + EXPECT_EQ((1 << 8) * 3 / 4, lower); + EXPECT_EQ(lower + (20 << 8) / kFrameSizeMs, higher); } TEST_F(DelayManagerTest, UpdateLongInterArrivalTime) { + SetPacketAudioLength(kFrameSizeMs); // First packet arrival. InsertNextPacket(); // Advance time by two frame size. IncreaseTime(2 * kFrameSizeMs); // Second packet arrival. InsertNextPacket(); - EXPECT_EQ(40, dm_->TargetDelayMs()); + EXPECT_EQ(2 << 8, dm_->TargetLevel()); // In Q8. + EXPECT_EQ(2, dm_->base_target_level()); + int lower, higher; + dm_->BufferLimits(&lower, &higher); + // Expect |lower| to be 75% of target level, and |higher| to be target level, + // but also at least 20 ms higher than |lower|, which is the limiting case + // here. + EXPECT_EQ((2 << 8) * 3 / 4, lower); + EXPECT_EQ(lower + (20 << 8) / kFrameSizeMs, higher); } TEST_F(DelayManagerTest, MaxDelay) { - const int kExpectedTarget = 5 * kFrameSizeMs; + const int kExpectedTarget = 5; + const int kTimeIncrement = kExpectedTarget * kFrameSizeMs; + SetPacketAudioLength(kFrameSizeMs); // First packet arrival. InsertNextPacket(); // Second packet arrival. - IncreaseTime(kExpectedTarget); + IncreaseTime(kTimeIncrement); InsertNextPacket(); // No limit is set. - EXPECT_EQ(kExpectedTarget, dm_->TargetDelayMs()); + EXPECT_EQ(kExpectedTarget << 8, dm_->TargetLevel()); - const int kMaxDelayMs = 3 * kFrameSizeMs; + int kMaxDelayPackets = kExpectedTarget - 2; + int kMaxDelayMs = kMaxDelayPackets * kFrameSizeMs; EXPECT_TRUE(dm_->SetMaximumDelay(kMaxDelayMs)); - IncreaseTime(kFrameSizeMs); + IncreaseTime(kTimeIncrement); InsertNextPacket(); - EXPECT_EQ(kMaxDelayMs, dm_->TargetDelayMs()); + EXPECT_EQ(kMaxDelayPackets << 8, dm_->TargetLevel()); // Target level at least should be one packet. EXPECT_FALSE(dm_->SetMaximumDelay(kFrameSizeMs - 1)); } TEST_F(DelayManagerTest, MinDelay) { - const int kExpectedTarget = 5 * kFrameSizeMs; + const int kExpectedTarget = 5; + const int kTimeIncrement = kExpectedTarget * kFrameSizeMs; + SetPacketAudioLength(kFrameSizeMs); // First packet arrival. InsertNextPacket(); // Second packet arrival. - IncreaseTime(kExpectedTarget); + IncreaseTime(kTimeIncrement); InsertNextPacket(); // No limit is applied. - EXPECT_EQ(kExpectedTarget, dm_->TargetDelayMs()); + EXPECT_EQ(kExpectedTarget << 8, dm_->TargetLevel()); - int kMinDelayMs = 7 * kFrameSizeMs; + int kMinDelayPackets = kExpectedTarget + 2; + int kMinDelayMs = kMinDelayPackets * kFrameSizeMs; dm_->SetMinimumDelay(kMinDelayMs); IncreaseTime(kFrameSizeMs); InsertNextPacket(); - EXPECT_EQ(kMinDelayMs, dm_->TargetDelayMs()); + EXPECT_EQ(kMinDelayPackets << 8, dm_->TargetLevel()); } TEST_F(DelayManagerTest, BaseMinimumDelayCheckValidRange) { + SetPacketAudioLength(kFrameSizeMs); + // Base minimum delay should be between [0, 10000] milliseconds. EXPECT_FALSE(dm_->SetBaseMinimumDelay(-1)); EXPECT_FALSE(dm_->SetBaseMinimumDelay(10001)); @@ -163,6 +207,7 @@ TEST_F(DelayManagerTest, BaseMinimumDelayCheckValidRange) { } TEST_F(DelayManagerTest, BaseMinimumDelayLowerThanMinimumDelay) { + SetPacketAudioLength(kFrameSizeMs); constexpr int kBaseMinimumDelayMs = 100; constexpr int kMinimumDelayMs = 200; @@ -176,6 +221,7 @@ TEST_F(DelayManagerTest, BaseMinimumDelayLowerThanMinimumDelay) { } TEST_F(DelayManagerTest, BaseMinimumDelayGreaterThanMinimumDelay) { + SetPacketAudioLength(kFrameSizeMs); constexpr int kBaseMinimumDelayMs = 70; constexpr int kMinimumDelayMs = 30; @@ -189,6 +235,7 @@ TEST_F(DelayManagerTest, BaseMinimumDelayGreaterThanMinimumDelay) { } TEST_F(DelayManagerTest, BaseMinimumDelayGreaterThanBufferSize) { + SetPacketAudioLength(kFrameSizeMs); constexpr int kBaseMinimumDelayMs = kMaxBufferSizeMs + 1; constexpr int kMinimumDelayMs = 12; constexpr int kMaximumDelayMs = 20; @@ -215,6 +262,7 @@ TEST_F(DelayManagerTest, BaseMinimumDelayGreaterThanBufferSize) { } TEST_F(DelayManagerTest, BaseMinimumDelayGreaterThanMaximumDelay) { + SetPacketAudioLength(kFrameSizeMs); constexpr int kMaximumDelayMs = 400; constexpr int kBaseMinimumDelayMs = kMaximumDelayMs + 1; constexpr int kMinimumDelayMs = 20; @@ -232,6 +280,7 @@ TEST_F(DelayManagerTest, BaseMinimumDelayGreaterThanMaximumDelay) { } TEST_F(DelayManagerTest, BaseMinimumDelayLowerThanMaxSize) { + SetPacketAudioLength(kFrameSizeMs); constexpr int kMaximumDelayMs = 400; constexpr int kBaseMinimumDelayMs = kMaximumDelayMs - 1; constexpr int kMinimumDelayMs = 20; @@ -252,6 +301,8 @@ TEST_F(DelayManagerTest, MinimumDelayMemorization) { // minimum delay then minimum delay is still memorized. This allows to // restore effective minimum delay to memorized minimum delay value when we // decrease base minimum delay. + SetPacketAudioLength(kFrameSizeMs); + constexpr int kBaseMinimumDelayMsLow = 10; constexpr int kMinimumDelayMs = 20; constexpr int kBaseMinimumDelayMsHigh = 30; @@ -272,29 +323,9 @@ TEST_F(DelayManagerTest, MinimumDelayMemorization) { } TEST_F(DelayManagerTest, BaseMinimumDelay) { - const int kExpectedTarget = 5 * kFrameSizeMs; - // First packet arrival. - InsertNextPacket(); - // Second packet arrival. - IncreaseTime(kExpectedTarget); - InsertNextPacket(); - - // No limit is applied. - EXPECT_EQ(kExpectedTarget, dm_->TargetDelayMs()); - - constexpr int kBaseMinimumDelayMs = 7 * kFrameSizeMs; - EXPECT_TRUE(dm_->SetBaseMinimumDelay(kBaseMinimumDelayMs)); - EXPECT_EQ(dm_->GetBaseMinimumDelay(), kBaseMinimumDelayMs); - - IncreaseTime(kFrameSizeMs); - InsertNextPacket(); - EXPECT_EQ(dm_->GetBaseMinimumDelay(), kBaseMinimumDelayMs); - EXPECT_EQ(kBaseMinimumDelayMs, dm_->TargetDelayMs()); -} - -TEST_F(DelayManagerTest, BaseMinimumDelayAffectsTargetDelay) { const int kExpectedTarget = 5; const int kTimeIncrement = kExpectedTarget * kFrameSizeMs; + SetPacketAudioLength(kFrameSizeMs); // First packet arrival. InsertNextPacket(); // Second packet arrival. @@ -302,7 +333,31 @@ TEST_F(DelayManagerTest, BaseMinimumDelayAffectsTargetDelay) { InsertNextPacket(); // No limit is applied. - EXPECT_EQ(kTimeIncrement, dm_->TargetDelayMs()); + EXPECT_EQ(kExpectedTarget << 8, dm_->TargetLevel()); + + constexpr int kBaseMinimumDelayPackets = kExpectedTarget + 2; + constexpr int kBaseMinimumDelayMs = kBaseMinimumDelayPackets * kFrameSizeMs; + EXPECT_TRUE(dm_->SetBaseMinimumDelay(kBaseMinimumDelayMs)); + EXPECT_EQ(dm_->GetBaseMinimumDelay(), kBaseMinimumDelayMs); + + IncreaseTime(kFrameSizeMs); + InsertNextPacket(); + EXPECT_EQ(dm_->GetBaseMinimumDelay(), kBaseMinimumDelayMs); + EXPECT_EQ(kBaseMinimumDelayPackets << 8, dm_->TargetLevel()); +} + +TEST_F(DelayManagerTest, BaseMinimumDealyAffectTargetLevel) { + const int kExpectedTarget = 5; + const int kTimeIncrement = kExpectedTarget * kFrameSizeMs; + SetPacketAudioLength(kFrameSizeMs); + // First packet arrival. + InsertNextPacket(); + // Second packet arrival. + IncreaseTime(kTimeIncrement); + InsertNextPacket(); + + // No limit is applied. + EXPECT_EQ(kExpectedTarget << 8, dm_->TargetLevel()); // Minimum delay is lower than base minimum delay, that is why base minimum // delay is used to calculate target level. @@ -320,19 +375,88 @@ TEST_F(DelayManagerTest, BaseMinimumDelayAffectsTargetDelay) { IncreaseTime(kFrameSizeMs); InsertNextPacket(); EXPECT_EQ(dm_->GetBaseMinimumDelay(), kBaseMinimumDelayMs); - EXPECT_EQ(kBaseMinimumDelayMs, dm_->TargetDelayMs()); + EXPECT_EQ(kBaseMinimumDelayPackets << 8, dm_->TargetLevel()); +} + +TEST_F(DelayManagerTest, EnableRtxHandling) { + enable_rtx_handling_ = true; + use_mock_histogram_ = true; + RecreateDelayManager(); + EXPECT_TRUE(mock_histogram_); + + // Insert first packet. + SetPacketAudioLength(kFrameSizeMs); + InsertNextPacket(); + + // Insert reordered packet. + EXPECT_CALL(*mock_histogram_, Add(2)); + dm_->Update(seq_no_ - 3, ts_ - 3 * kFrameSizeMs, kFs); + + // Insert another reordered packet. + EXPECT_CALL(*mock_histogram_, Add(1)); + dm_->Update(seq_no_ - 2, ts_ - 2 * kFrameSizeMs, kFs); + + // Insert the next packet in order and verify that the inter-arrival time is + // estimated correctly. + IncreaseTime(kFrameSizeMs); + EXPECT_CALL(*mock_histogram_, Add(0)); + InsertNextPacket(); +} + +// Tests that skipped sequence numbers (simulating empty packets) are handled +// correctly. +// TODO(jakobi): Make delay manager independent of sequence numbers. +TEST_F(DelayManagerTest, EmptyPacketsReported) { + SetPacketAudioLength(kFrameSizeMs); + // First packet arrival. + InsertNextPacket(); + + // Advance time by one frame size. + IncreaseTime(kFrameSizeMs); + + // Advance the sequence number by 5, simulating that 5 empty packets were + // received, but never inserted. + seq_no_ += 10; + for (int j = 0; j < 10; ++j) { + dm_->RegisterEmptyPacket(); + } + + // Second packet arrival. + InsertNextPacket(); + + EXPECT_EQ(1 << 8, dm_->TargetLevel()); // In Q8. +} + +// Same as above, but do not call RegisterEmptyPacket. Target level stays the +// same. +TEST_F(DelayManagerTest, EmptyPacketsNotReported) { + SetPacketAudioLength(kFrameSizeMs); + // First packet arrival. + InsertNextPacket(); + + // Advance time by one frame size. + IncreaseTime(kFrameSizeMs); + + // Advance the sequence number by 10, simulating that 10 empty packets were + // received, but never inserted. + seq_no_ += 10; + + // Second packet arrival. + InsertNextPacket(); + + EXPECT_EQ(1 << 8, dm_->TargetLevel()); // In Q8. } TEST_F(DelayManagerTest, Failures) { // Wrong sample rate. - EXPECT_EQ(absl::nullopt, dm_->Update(0, -1)); + EXPECT_EQ(absl::nullopt, dm_->Update(0, 0, -1)); // Wrong packet size. EXPECT_EQ(-1, dm_->SetPacketAudioLength(0)); EXPECT_EQ(-1, dm_->SetPacketAudioLength(-1)); // Minimum delay higher than a maximum delay is not accepted. - EXPECT_TRUE(dm_->SetMaximumDelay(20)); - EXPECT_FALSE(dm_->SetMinimumDelay(40)); + EXPECT_TRUE(dm_->SetMaximumDelay(10)); + EXPECT_FALSE(dm_->SetMinimumDelay(20)); // Maximum delay less than minimum delay is not accepted. EXPECT_TRUE(dm_->SetMaximumDelay(100)); @@ -386,6 +510,7 @@ TEST_F(DelayManagerTest, RelativeArrivalDelay) { use_mock_histogram_ = true; RecreateDelayManager(); + SetPacketAudioLength(kFrameSizeMs); InsertNextPacket(); IncreaseTime(kFrameSizeMs); @@ -394,20 +519,21 @@ TEST_F(DelayManagerTest, RelativeArrivalDelay) { IncreaseTime(2 * kFrameSizeMs); EXPECT_CALL(*mock_histogram_, Add(1)); // 20ms delayed. - dm_->Update(ts_, kFs); + dm_->Update(seq_no_, ts_, kFs); IncreaseTime(2 * kFrameSizeMs); EXPECT_CALL(*mock_histogram_, Add(2)); // 40ms delayed. - dm_->Update(ts_ + kTsIncrement, kFs); + dm_->Update(seq_no_ + 1, ts_ + kTsIncrement, kFs); EXPECT_CALL(*mock_histogram_, Add(1)); // Reordered, 20ms delayed. - dm_->Update(ts_, kFs); + dm_->Update(seq_no_, ts_, kFs); } TEST_F(DelayManagerTest, MaxDelayHistory) { use_mock_histogram_ = true; RecreateDelayManager(); + SetPacketAudioLength(kFrameSizeMs); InsertNextPacket(); // Insert 20 ms iat delay in the delay history. @@ -421,10 +547,11 @@ TEST_F(DelayManagerTest, MaxDelayHistory) { IncreaseTime(kMaxHistoryMs + kFrameSizeMs); ts_ += kFs * kMaxHistoryMs / 1000; EXPECT_CALL(*mock_histogram_, Add(0)); // Not delayed. - dm_->Update(ts_, kFs); + dm_->Update(seq_no_, ts_, kFs); } TEST_F(DelayManagerTest, RelativeArrivalDelayStatistic) { + SetPacketAudioLength(kFrameSizeMs); EXPECT_EQ(absl::nullopt, InsertNextPacket()); IncreaseTime(kFrameSizeMs); EXPECT_EQ(0, InsertNextPacket()); @@ -433,4 +560,38 @@ TEST_F(DelayManagerTest, RelativeArrivalDelayStatistic) { EXPECT_EQ(20, InsertNextPacket()); } +TEST_F(DelayManagerTest, DecelerationTargetLevelOffset) { + SetPacketAudioLength(kFrameSizeMs); + + // Deceleration target level offset follows the value hardcoded in + // delay_manager.cc. + constexpr int kDecelerationTargetLevelOffsetMs = 85 << 8; // In Q8. + // Border value where |x * 3/4 = target_level - x|. + constexpr int kBoarderTargetLevel = kDecelerationTargetLevelOffsetMs * 4; + { + // Test that for a low target level, default behaviour is intact. + const int target_level_ms = kBoarderTargetLevel / kFrameSizeMs - 1; + + int lower, higher; // In Q8. + dm_->BufferLimits(target_level_ms, &lower, &higher); + + // Default behaviour of taking 75% of target level. + EXPECT_EQ(target_level_ms * 3 / 4, lower); + EXPECT_EQ(target_level_ms, higher); + } + + { + // Test that for the high target level, |lower| is below target level by + // fixed |kOffset|. + const int target_level_ms = kBoarderTargetLevel / kFrameSizeMs + 1; + + int lower, higher; // In Q8. + dm_->BufferLimits(target_level_ms, &lower, &higher); + + EXPECT_EQ(target_level_ms - kDecelerationTargetLevelOffsetMs / kFrameSizeMs, + lower); + EXPECT_EQ(target_level_ms, higher); + } +} + } // namespace webrtc diff --git a/modules/audio_coding/neteq/neteq_impl_unittest.cc b/modules/audio_coding/neteq/neteq_impl_unittest.cc index 44660fc483..5c7259f00b 100644 --- a/modules/audio_coding/neteq/neteq_impl_unittest.cc +++ b/modules/audio_coding/neteq/neteq_impl_unittest.cc @@ -804,10 +804,8 @@ TEST_P(NetEqImplTestSampleRateParameter, EXPECT_EQ(NetEq::kOK, neteq_->GetAudio(&output, &muted)); } - // Insert a few packets to avoid postpone decoding after expand. - for (size_t i = 0; i < 5; ++i) { - insert_packet(); - } + // Insert one more packet. + insert_packet(); // Pull audio until the newly inserted packet is decoded and the PLC ends. while (output.speech_type_ != AudioFrame::kNormalSpeech) { @@ -883,10 +881,8 @@ TEST_P(NetEqImplTestSampleRateParameter, AudioInterruptionLogged) { EXPECT_NE(AudioFrame::kNormalSpeech, output.speech_type_); } - // Insert a few packets to avoid postpone decoding after expand. - for (size_t i = 0; i < 5; ++i) { - insert_packet(); - } + // Insert one more packet. + insert_packet(); // Pull audio until the newly inserted packet is decoded and the PLC ends. while (output.speech_type_ != AudioFrame::kNormalSpeech) { @@ -1303,7 +1299,7 @@ TEST_F(NetEqImplTest, DecodingError) { SdpAudioFormat("L16", 8000, 1))); // Insert packets. - for (int i = 0; i < 20; ++i) { + for (int i = 0; i < 6; ++i) { rtp_header.sequenceNumber += 1; rtp_header.timestamp += kFrameLengthSamples; EXPECT_EQ(NetEq::kOK, neteq_->InsertPacket(rtp_header, payload)); diff --git a/modules/audio_coding/neteq/neteq_unittest.cc b/modules/audio_coding/neteq/neteq_unittest.cc index c6d514d827..d7030bfd64 100644 --- a/modules/audio_coding/neteq/neteq_unittest.cc +++ b/modules/audio_coding/neteq/neteq_unittest.cc @@ -84,16 +84,16 @@ TEST_F(NetEqDecodingTest, MAYBE_TestBitExactness) { webrtc::test::ResourcePath("audio_coding/neteq_universal_new", "rtp"); const std::string output_checksum = - PlatformChecksum("68ec266d2d152dfc0d938484e7936f6af4f803e3", - "1c243feb35e3e9ab37039eddf5b3c3ecfca3c60c", "not used", - "68ec266d2d152dfc0d938484e7936f6af4f803e3", - "f68c546a43bb25743297c9c0c9027e8424b8e10b"); + PlatformChecksum("6ae9f643dc3e5f3452d28a772eef7e00e74158bc", + "f4374430e870d66268c1b8e22fb700eb072d567e", "not used", + "6ae9f643dc3e5f3452d28a772eef7e00e74158bc", + "8d73c98645917cdeaaa01c20cf095ccc5a10b2b5"); const std::string network_stats_checksum = - PlatformChecksum("2a5516cdc1c6af9f1d9d3c2f95ed292f509311c7", - "e96a7f081ebc111f49c7373d3728274057012ae9", "not used", - "2a5516cdc1c6af9f1d9d3c2f95ed292f509311c7", - "2a5516cdc1c6af9f1d9d3c2f95ed292f509311c7"); + PlatformChecksum("8e50f528f245b7957db20ab406a72d81be60f5f4", + "4260b22ea6d2723b2d573e50d2c1476680c7fa4c", "not used", + "8e50f528f245b7957db20ab406a72d81be60f5f4", + "8e50f528f245b7957db20ab406a72d81be60f5f4"); DecodeAndCompare(input_rtp_file, output_checksum, network_stats_checksum, absl::GetFlag(FLAGS_gen_ref)); @@ -113,13 +113,13 @@ TEST_F(NetEqDecodingTest, MAYBE_TestOpusBitExactness) { "554ad4133934e3920f97575579a46f674683d77c" "|de316e2bfb15192edb820fe5fb579d11ff5a524b"; const std::string output_checksum = PlatformChecksum( - maybe_sse, "b3fac4ad4f6ea384aff676ee1ea816bd70415490", - "373ccd99c147cd3fcef0e7dcad6f87d0f8e5a1c0", maybe_sse, maybe_sse); + maybe_sse, "459c356a0ef245ddff381f7d82d205d426ef2002", + "625055e5eb0e6de2c9d170b4494eadc5afab08c8", maybe_sse, maybe_sse); const std::string network_stats_checksum = PlatformChecksum("ec29e047b019a86ec06e2c40643143dc1975c69f", - "ce6f519bc1220b003944ac5d9db077665a06834e", - "abb686d3ac6fac0001ca8d45a6ca6f5aefb2f9d6", + "0c24649824eb7147d4891b0767e86e732dd6ecc8", + "10f3e0b66c6947f78d60301454f2841033a6fcc0", "ec29e047b019a86ec06e2c40643143dc1975c69f", "ec29e047b019a86ec06e2c40643143dc1975c69f"); @@ -138,14 +138,14 @@ TEST_F(NetEqDecodingTest, MAYBE_TestOpusDtxBitExactness) { webrtc::test::ResourcePath("audio_coding/neteq_opus_dtx", "rtp"); const std::string maybe_sse = - "0fb0a3d6b3758ca6e108368bb777cd38d0a865af" - "|79cfb99a21338ba977eb0e15eb8464e2db9436f8"; + "df5d1d3019bf3764829b84f4fb315721f4adde29" + "|5935d2fad14a69a8b61dbc8e6f2d37c8c0814925"; const std::string output_checksum = PlatformChecksum( - maybe_sse, "b6632690f8d7c2340c838df2821fc014f1cc8360", - "f890b9eb9bc5ab8313489230726b297f6a0825af", maybe_sse, maybe_sse); + maybe_sse, "551df04e8f45cd99eff28503edf0cf92974898ac", + "709a3f0f380393d3a67bace10e2265b90a6ebbeb", maybe_sse, maybe_sse); const std::string network_stats_checksum = - "18983bb67a57628c604dbdefa99574c6e0c5bb48"; + "80f5283ac71b27596204210152927666c1732de4"; DecodeAndCompare(input_rtp_file, output_checksum, network_stats_checksum, absl::GetFlag(FLAGS_gen_ref)); @@ -737,10 +737,8 @@ TEST_F(NetEqDecodingTestWithMutedState, MutedStateOldPacket) { GetAudioUntilMuted(); EXPECT_NE(AudioFrame::kNormalSpeech, out_frame_.speech_type_); - // Insert a few packets which are older than the first packet. - for (int i = 0; i < 5; ++i) { - InsertPacket(kSamples * (i - 1000)); - } + // Insert packet which is older than the first packet. + InsertPacket(kSamples * (counter_ - 1000)); EXPECT_FALSE(GetAudioReturnMuted()); EXPECT_EQ(AudioFrame::kNormalSpeech, out_frame_.speech_type_); } @@ -855,11 +853,9 @@ TEST_F(NetEqDecodingTestTwoInstances, CompareMutedStateOnOff) { // Insert new data. Timestamp is corrected for the time elapsed since the last // packet. - for (int i = 0; i < 5; ++i) { - PopulateRtpInfo(0, kSamples * 1000 + kSamples * i, &rtp_info); - EXPECT_EQ(0, neteq_->InsertPacket(rtp_info, payload)); - EXPECT_EQ(0, neteq2_->InsertPacket(rtp_info, payload)); - } + PopulateRtpInfo(0, kSamples * 1000, &rtp_info); + EXPECT_EQ(0, neteq_->InsertPacket(rtp_info, payload)); + EXPECT_EQ(0, neteq2_->InsertPacket(rtp_info, payload)); int counter = 0; while (out_frame1.speech_type_ != AudioFrame::kNormalSpeech) { @@ -1268,7 +1264,7 @@ TEST(NetEqOutputDelayTest, RunTestWithFieldTrial) { // The base delay values are taken from the resuts of the non-delayed case in // NetEqOutputDelayTest.RunTest above. - EXPECT_EQ(20 + kExpectedDelayMs, result.target_delay_ms); + EXPECT_EQ(10 + kExpectedDelayMs, result.target_delay_ms); EXPECT_EQ(24 + kExpectedDelayMs, result.filtered_current_delay_ms); } @@ -1283,7 +1279,7 @@ TEST(NetEqOutputDelayTest, RunTestWithFieldTrialOddValue) { // The base delay values are taken from the resuts of the non-delayed case in // NetEqOutputDelayTest.RunTest above. - EXPECT_EQ(20 + kRoundedDelayMs, result.target_delay_ms); + EXPECT_EQ(10 + kRoundedDelayMs, result.target_delay_ms); EXPECT_EQ(24 + kRoundedDelayMs, result.filtered_current_delay_ms); }