diff --git a/modules/audio_coding/neteq/neteq_impl.cc b/modules/audio_coding/neteq/neteq_impl.cc index 38cabd93c1..6a9371c7f7 100644 --- a/modules/audio_coding/neteq/neteq_impl.cc +++ b/modules/audio_coding/neteq/neteq_impl.cc @@ -201,6 +201,7 @@ int NetEqImpl::GetAudio(AudioFrame* audio_frame, if (GetAudioInternal(audio_frame, action_override) != 0) { return kFail; } + stats_->IncreaseCounter(output_size_samples_, fs_hz_); RTC_DCHECK_EQ( audio_frame->sample_rate_hz_, rtc::dchecked_cast(audio_frame->samples_per_channel_ * 100)); @@ -733,7 +734,6 @@ int NetEqImpl::GetAudioInternal(AudioFrame* audio_frame, bool play_dtmf; last_decoded_packet_infos_.clear(); tick_timer_->Increment(); - stats_->IncreaseCounter(output_size_samples_, fs_hz_); // Check for muted state. if (enable_muted_state_ && expand_->Muted() && packet_buffer_->Empty()) { diff --git a/modules/audio_coding/neteq/neteq_impl_unittest.cc b/modules/audio_coding/neteq/neteq_impl_unittest.cc index 021d122a40..6d9d6feeb5 100644 --- a/modules/audio_coding/neteq/neteq_impl_unittest.cc +++ b/modules/audio_coding/neteq/neteq_impl_unittest.cc @@ -384,6 +384,35 @@ TEST_F(NetEqImplTest, InsertPacket) { /*receive_time=*/clock_.CurrentTime()); } +TEST_F(NetEqImplTest, CountStatsAfterFirstDecodedPacket) { + UseNoMocks(); + CreateInstance(); + const uint8_t kPayloadType = 17; // Just an arbitrary number. + EXPECT_TRUE(neteq_->RegisterPayloadType(kPayloadType, + SdpAudioFormat("l16", 8000, 1))); + const size_t kPayloadLengthSamples = 80; + const size_t kPayloadLengthBytes = 2 * kPayloadLengthSamples; // PCM 16-bit. + uint8_t payload[kPayloadLengthBytes] = {0}; + RTPHeader rtp_header; + rtp_header.payloadType = kPayloadType; + rtp_header.sequenceNumber = 0x1234; + rtp_header.timestamp = 0x12345678; + rtp_header.ssrc = 0x87654321; + AudioFrame frame; + // Get audio a couple of times to make sure that samples received remains + // zero. + for (int i = 0; i < 3; ++i) { + neteq_->GetAudio(&frame); + EXPECT_EQ(neteq_->GetLifetimeStatistics().concealed_samples, 0u); + EXPECT_EQ(neteq_->GetLifetimeStatistics().total_samples_received, 0u); + } + neteq_->InsertPacket(rtp_header, payload, clock_.CurrentTime()); + neteq_->GetAudio(&frame); + EXPECT_EQ(neteq_->GetLifetimeStatistics().concealed_samples, 0u); + EXPECT_EQ(neteq_->GetLifetimeStatistics().total_samples_received, + kPayloadLengthSamples); +} + TEST_F(NetEqImplTest, InsertPacketsUntilBufferIsFull) { UseNoMocks(); CreateInstance(); diff --git a/modules/audio_coding/neteq/neteq_unittest.cc b/modules/audio_coding/neteq/neteq_unittest.cc index 1fc97100e3..394c5a7782 100644 --- a/modules/audio_coding/neteq/neteq_unittest.cc +++ b/modules/audio_coding/neteq/neteq_unittest.cc @@ -81,7 +81,7 @@ TEST_F(NetEqDecodingTest, MAYBE_TestOpusBitExactness) { "cefd2de4adfa8f6a9b66a3639ad63c2f6779d0cd"; const std::string network_stats_checksum = - "5f2c8e3dff9cff55dd7a9f4167939de001566d95|" + "06f6b9a86aeae6317fd25a36edf9ed16f35e798f|" "80ab17c17da030d4f2dfbf314ac44aacdadd7f0c"; DecodeAndCompare(input_rtp_file, output_checksum, network_stats_checksum, @@ -103,7 +103,7 @@ TEST_F(NetEqDecodingTest, MAYBE_TestOpusDtxBitExactness) { "5d13affec87bf4cc8c7667f0cd0d25e1ad09c7c3"; const std::string network_stats_checksum = - "92b0fdcbf8bb9354d40140b7312f2fb76a078555"; + "6af74a713749cc4343464718b6af54f1e5b06ad9"; DecodeAndCompare(input_rtp_file, output_checksum, network_stats_checksum, absl::GetFlag(FLAGS_gen_ref)); @@ -660,7 +660,7 @@ TEST_F(NetEqDecodingTestWithMutedState, MutedState) { // NetEqNetworkStatistics::expand_rate tells the fraction of samples that were // concealment samples, in Q14 (16384 = 100%) .The vast majority should be // concealment samples in this test. - EXPECT_GT(stats.expand_rate, 14000); + EXPECT_GT(stats.expand_rate, 13000); // And, it should be greater than the speech_expand_rate. EXPECT_GT(stats.expand_rate, stats.speech_expand_rate); } diff --git a/modules/audio_coding/neteq/statistics_calculator.cc b/modules/audio_coding/neteq/statistics_calculator.cc index 4f0f74a856..cfea14ebd6 100644 --- a/modules/audio_coding/neteq/statistics_calculator.cc +++ b/modules/audio_coding/neteq/statistics_calculator.cc @@ -155,6 +155,9 @@ void StatisticsCalculator::ResetMcu() { void StatisticsCalculator::ExpandedVoiceSamples(size_t num_samples, bool is_new_concealment_event) { + if (!decoded_output_played_) { + return; + } expanded_speech_samples_ += num_samples; ConcealedSamplesCorrection(rtc::dchecked_cast(num_samples), true); lifetime_stats_.concealment_events += is_new_concealment_event; @@ -162,18 +165,27 @@ void StatisticsCalculator::ExpandedVoiceSamples(size_t num_samples, void StatisticsCalculator::ExpandedNoiseSamples(size_t num_samples, bool is_new_concealment_event) { + if (!decoded_output_played_) { + return; + } expanded_noise_samples_ += num_samples; ConcealedSamplesCorrection(rtc::dchecked_cast(num_samples), false); lifetime_stats_.concealment_events += is_new_concealment_event; } void StatisticsCalculator::ExpandedVoiceSamplesCorrection(int num_samples) { + if (!decoded_output_played_) { + return; + } expanded_speech_samples_ = AddIntToSizeTWithLowerCap(num_samples, expanded_speech_samples_); ConcealedSamplesCorrection(num_samples, true); } void StatisticsCalculator::ExpandedNoiseSamplesCorrection(int num_samples) { + if (!decoded_output_played_) { + return; + } expanded_noise_samples_ = AddIntToSizeTWithLowerCap(num_samples, expanded_noise_samples_); ConcealedSamplesCorrection(num_samples, false); @@ -184,6 +196,9 @@ void StatisticsCalculator::DecodedOutputPlayed() { } void StatisticsCalculator::EndExpandEvent(int fs_hz) { + if (!decoded_output_played_) { + return; + } RTC_DCHECK_GE(lifetime_stats_.concealed_samples, concealed_samples_at_event_end_); const int event_duration_ms = @@ -201,6 +216,9 @@ void StatisticsCalculator::EndExpandEvent(int fs_hz) { void StatisticsCalculator::ConcealedSamplesCorrection(int num_samples, bool is_voice) { + if (!decoded_output_played_) { + return; + } if (num_samples < 0) { // Store negative correction to subtract from future positive additions. // See also the function comment in the header file. @@ -226,18 +244,27 @@ void StatisticsCalculator::ConcealedSamplesCorrection(int num_samples, } void StatisticsCalculator::PreemptiveExpandedSamples(size_t num_samples) { + if (!decoded_output_played_) { + return; + } preemptive_samples_ += num_samples; operations_and_state_.preemptive_samples += num_samples; lifetime_stats_.inserted_samples_for_deceleration += num_samples; } void StatisticsCalculator::AcceleratedSamples(size_t num_samples) { + if (!decoded_output_played_) { + return; + } accelerate_samples_ += num_samples; operations_and_state_.accelerate_samples += num_samples; lifetime_stats_.removed_samples_for_acceleration += num_samples; } void StatisticsCalculator::GeneratedNoiseSamples(size_t num_samples) { + if (!decoded_output_played_) { + return; + } lifetime_stats_.generated_noise_samples += num_samples; } @@ -255,6 +282,9 @@ void StatisticsCalculator::SecondaryPacketsReceived(size_t num_packets) { } void StatisticsCalculator::IncreaseCounter(size_t num_samples, int fs_hz) { + if (!decoded_output_played_) { + return; + } const int time_step_ms = rtc::CheckedDivExact(static_cast(1000 * num_samples), fs_hz); delayed_packet_outage_counter_.AdvanceClock(time_step_ms); @@ -268,10 +298,14 @@ void StatisticsCalculator::IncreaseCounter(size_t num_samples, int fs_hz) { lifetime_stats_.total_samples_received += num_samples; expand_uma_logger_.UpdateSampleCounter(lifetime_stats_.concealed_samples, fs_hz); - speech_expand_uma_logger_.UpdateSampleCounter( - lifetime_stats_.concealed_samples - - lifetime_stats_.silent_concealed_samples, - fs_hz); + uint64_t speech_concealed_samples = 0; + if (lifetime_stats_.concealed_samples > + lifetime_stats_.silent_concealed_samples) { + speech_concealed_samples = lifetime_stats_.concealed_samples - + lifetime_stats_.silent_concealed_samples; + } + speech_expand_uma_logger_.UpdateSampleCounter(speech_concealed_samples, + fs_hz); } void StatisticsCalculator::JitterBufferDelay(size_t num_samples, diff --git a/modules/audio_coding/neteq/statistics_calculator_unittest.cc b/modules/audio_coding/neteq/statistics_calculator_unittest.cc index 6bb40f1230..a8ad359ab0 100644 --- a/modules/audio_coding/neteq/statistics_calculator_unittest.cc +++ b/modules/audio_coding/neteq/statistics_calculator_unittest.cc @@ -17,6 +17,7 @@ namespace webrtc { TEST(LifetimeStatistics, TotalSamplesReceived) { TickTimer timer; StatisticsCalculator stats(&timer); + stats.DecodedOutputPlayed(); for (int i = 0; i < 10; ++i) { stats.IncreaseCounter(480, 48000); // 10 ms at 48 kHz. } @@ -26,6 +27,7 @@ TEST(LifetimeStatistics, TotalSamplesReceived) { TEST(LifetimeStatistics, SamplesConcealed) { TickTimer timer; StatisticsCalculator stats(&timer); + stats.DecodedOutputPlayed(); stats.ExpandedVoiceSamples(100, false); stats.ExpandedNoiseSamples(17, false); EXPECT_EQ(100u + 17u, stats.GetLifetimeStatistics().concealed_samples); @@ -38,6 +40,7 @@ TEST(LifetimeStatistics, SamplesConcealed) { TEST(LifetimeStatistics, SamplesConcealedCorrection) { TickTimer timer; StatisticsCalculator stats(&timer); + stats.DecodedOutputPlayed(); stats.ExpandedVoiceSamples(100, false); EXPECT_EQ(100u, stats.GetLifetimeStatistics().concealed_samples); stats.ExpandedVoiceSamplesCorrection(-10); @@ -60,6 +63,7 @@ TEST(LifetimeStatistics, SamplesConcealedCorrection) { TEST(LifetimeStatistics, NoUpdateOnTimeStretch) { TickTimer timer; StatisticsCalculator stats(&timer); + stats.DecodedOutputPlayed(); stats.ExpandedVoiceSamples(100, false); stats.AcceleratedSamples(4711); stats.PreemptiveExpandedSamples(17); @@ -70,6 +74,7 @@ TEST(LifetimeStatistics, NoUpdateOnTimeStretch) { TEST(StatisticsCalculator, ExpandedSamplesCorrection) { TickTimer timer; StatisticsCalculator stats(&timer); + stats.DecodedOutputPlayed(); NetEqNetworkStatistics stats_output; constexpr int kSampleRateHz = 48000; constexpr int k10MsSamples = kSampleRateHz / 100; @@ -243,4 +248,19 @@ TEST(StatisticsCalculator, JitterBufferDelay) { EXPECT_EQ(lts.jitter_buffer_emitted_count, 960ul); } +TEST(StatisticsCalculator, CountStatsAfterFirstDecodedPacket) { + TickTimer timer; + StatisticsCalculator stats(&timer); + stats.IncreaseCounter(/*num_samples=*/480, /*fs_hz=*/48000); + stats.ExpandedVoiceSamples(/*num_samples=*/480, + /*is_new_concealment_event=*/true); + NetEqLifetimeStatistics lts = stats.GetLifetimeStatistics(); + EXPECT_EQ(lts.total_samples_received, 0u); + EXPECT_EQ(lts.concealed_samples, 0u); + stats.DecodedOutputPlayed(); + stats.IncreaseCounter(/*num_samples=*/480, /*fs_hz=*/48000); + lts = stats.GetLifetimeStatistics(); + EXPECT_EQ(lts.total_samples_received, 480u); +} + } // namespace webrtc