diff --git a/modules/audio_coding/neteq/neteq_impl.cc b/modules/audio_coding/neteq/neteq_impl.cc index cdf590baa3..2d50225652 100644 --- a/modules/audio_coding/neteq/neteq_impl.cc +++ b/modules/audio_coding/neteq/neteq_impl.cc @@ -374,9 +374,11 @@ int NetEqImpl::NetworkStatistics(NetEqNetworkStatistics* stats) { sync_buffer_->FutureLength(); assert(delay_manager_.get()); assert(decision_logic_.get()); + const int ms_per_packet = rtc::dchecked_cast( + decision_logic_->packet_length_samples() / (fs_hz_ / 1000)); + stats_.PopulateDelayManagerStats(ms_per_packet, *delay_manager_.get(), stats); stats_.GetNetworkStatistics(fs_hz_, total_samples_in_buffers, - decoder_frame_length_, *delay_manager_.get(), - *decision_logic_.get(), stats); + decoder_frame_length_, stats); return 0; } diff --git a/modules/audio_coding/neteq/statistics_calculator.cc b/modules/audio_coding/neteq/statistics_calculator.cc index 09ced6a752..4e034e63a0 100644 --- a/modules/audio_coding/neteq/statistics_calculator.cc +++ b/modules/audio_coding/neteq/statistics_calculator.cc @@ -14,7 +14,6 @@ #include // memset #include -#include "modules/audio_coding/neteq/decision_logic.h" #include "modules/audio_coding/neteq/delay_manager.h" #include "rtc_base/checks.h" #include "rtc_base/safe_conversions.h" @@ -255,24 +254,13 @@ void StatisticsCalculator::GetNetworkStatistics( int fs_hz, size_t num_samples_in_buffers, size_t samples_per_packet, - const DelayManager& delay_manager, - const DecisionLogic& decision_logic, NetEqNetworkStatistics *stats) { - if (fs_hz <= 0 || !stats) { - assert(false); - return; - } + RTC_DCHECK_GT(fs_hz, 0); + RTC_DCHECK(stats); stats->added_zero_samples = added_zero_samples_; stats->current_buffer_size_ms = static_cast(num_samples_in_buffers * 1000 / fs_hz); - const int ms_per_packet = rtc::dchecked_cast( - decision_logic.packet_length_samples() / (fs_hz / 1000)); - stats->preferred_buffer_size_ms = (delay_manager.TargetLevel() >> 8) * - ms_per_packet; - stats->jitter_peaks_found = delay_manager.PeakFound(); - stats->clockdrift_ppm = - rtc::saturated_cast(delay_manager.EstimatedClockDriftPpm()); stats->packet_loss_rate = CalculateQ14Ratio(lost_timestamps_, timestamps_since_last_report_); @@ -331,6 +319,18 @@ void StatisticsCalculator::GetNetworkStatistics( Reset(); } +void StatisticsCalculator::PopulateDelayManagerStats( + int ms_per_packet, + const DelayManager& delay_manager, + NetEqNetworkStatistics* stats) { + RTC_DCHECK(stats); + stats->preferred_buffer_size_ms = + (delay_manager.TargetLevel() >> 8) * ms_per_packet; + stats->jitter_peaks_found = delay_manager.PeakFound(); + stats->clockdrift_ppm = + rtc::saturated_cast(delay_manager.EstimatedClockDriftPpm()); +} + NetEqLifetimeStatistics StatisticsCalculator::GetLifetimeStatistics() const { return lifetime_stats_; } diff --git a/modules/audio_coding/neteq/statistics_calculator.h b/modules/audio_coding/neteq/statistics_calculator.h index 232ca9acd0..5c2fbf3693 100644 --- a/modules/audio_coding/neteq/statistics_calculator.h +++ b/modules/audio_coding/neteq/statistics_calculator.h @@ -20,8 +20,6 @@ namespace webrtc { -// Forward declarations. -class DecisionLogic; class DelayManager; // This class handles various network statistics in NetEq. @@ -91,14 +89,22 @@ class StatisticsCalculator { // Returns the current network statistics in |stats|. The current sample rate // is |fs_hz|, the total number of samples in packet buffer and sync buffer // yet to play out is |num_samples_in_buffers|, and the number of samples per - // packet is |samples_per_packet|. + // packet is |samples_per_packet|. The method does not populate + // |preferred_buffer_size_ms|, |jitter_peaks_found| or |clockdrift_ppm|; use + // the PopulateDelayManagerStats method for those. void GetNetworkStatistics(int fs_hz, size_t num_samples_in_buffers, size_t samples_per_packet, - const DelayManager& delay_manager, - const DecisionLogic& decision_logic, NetEqNetworkStatistics *stats); + // Populates |preferred_buffer_size_ms|, |jitter_peaks_found| and + // |clockdrift_ppm| in |stats|. This is a convenience method, and does not + // strictly have to be in the StatisticsCalculator class, but it makes sense + // since all other stats fields are populated by that class. + static void PopulateDelayManagerStats(int ms_per_packet, + const DelayManager& delay_manager, + NetEqNetworkStatistics* stats); + // Returns a copy of this class's lifetime statistics. These statistics are // never reset. NetEqLifetimeStatistics GetLifetimeStatistics() const; diff --git a/modules/audio_coding/neteq/statistics_calculator_unittest.cc b/modules/audio_coding/neteq/statistics_calculator_unittest.cc index 0cc868aeb3..0a4901d51b 100644 --- a/modules/audio_coding/neteq/statistics_calculator_unittest.cc +++ b/modules/audio_coding/neteq/statistics_calculator_unittest.cc @@ -63,4 +63,45 @@ TEST(LifetimeStatistics, NoUpdateOnTimeStretch) { EXPECT_EQ(200u, stats.GetLifetimeStatistics().concealed_samples); } +TEST(StatisticsCalculator, ExpandedSamplesCorrection) { + StatisticsCalculator stats; + NetEqNetworkStatistics stats_output; + constexpr int kSampleRateHz = 48000; + constexpr int k10MsSamples = kSampleRateHz / 100; + constexpr int kPacketSizeMs = 20; + constexpr size_t kSamplesPerPacket = kPacketSizeMs * kSampleRateHz / 1000; + // Assume 2 packets in the buffer. + constexpr size_t kNumSamplesInBuffer = 2 * kSamplesPerPacket; + + // Advance time by 10 ms. + stats.IncreaseCounter(k10MsSamples, kSampleRateHz); + + stats.GetNetworkStatistics(kSampleRateHz, kNumSamplesInBuffer, + kSamplesPerPacket, &stats_output); + + EXPECT_EQ(0u, stats_output.expand_rate); + EXPECT_EQ(0u, stats_output.speech_expand_rate); + + // Correct with a negative value. + stats.ExpandedVoiceSamplesCorrection(-100); + stats.ExpandedNoiseSamplesCorrection(-100); + stats.IncreaseCounter(k10MsSamples, kSampleRateHz); + stats.GetNetworkStatistics(kSampleRateHz, kNumSamplesInBuffer, + kSamplesPerPacket, &stats_output); + // Expect no change, since negative values are disallowed. + EXPECT_EQ(0u, stats_output.expand_rate); + EXPECT_EQ(0u, stats_output.speech_expand_rate); + + // Correct with a positive value. + stats.ExpandedVoiceSamplesCorrection(50); + stats.ExpandedNoiseSamplesCorrection(200); + stats.IncreaseCounter(k10MsSamples, kSampleRateHz); + stats.GetNetworkStatistics(kSampleRateHz, kNumSamplesInBuffer, + kSamplesPerPacket, &stats_output); + // Calculate expected rates in Q14. Expand rate is noise + voice, while + // speech expand rate is only voice. + EXPECT_EQ(((50u + 200u) << 14) / k10MsSamples, stats_output.expand_rate); + EXPECT_EQ((50u << 14) / k10MsSamples, stats_output.speech_expand_rate); +} + } // namespace webrtc