diff --git a/modules/audio_coding/neteq/include/neteq.h b/modules/audio_coding/neteq/include/neteq.h index 549d355ae0..8721663360 100644 --- a/modules/audio_coding/neteq/include/neteq.h +++ b/modules/audio_coding/neteq/include/neteq.h @@ -71,8 +71,12 @@ struct NetEqLifetimeStatistics { uint64_t concealment_events = 0; uint64_t jitter_buffer_delay_ms = 0; uint64_t jitter_buffer_emitted_count = 0; + uint64_t inserted_samples_for_deceleration = 0; + uint64_t removed_samples_for_acceleration = 0; + uint64_t silent_concealed_samples = 0; + uint64_t fec_packets_received = 0; + uint64_t fec_packets_discarded = 0; // Below stats are not part of the spec. - uint64_t voice_concealed_samples = 0; uint64_t delayed_packet_outage_samples = 0; // This is sum of relative packet arrival delays of received packets so far. // Since end-to-end delay of a packet is difficult to measure and is not diff --git a/modules/audio_coding/neteq/neteq_impl.cc b/modules/audio_coding/neteq/neteq_impl.cc index b7f5579c9b..fcb09bebef 100644 --- a/modules/audio_coding/neteq/neteq_impl.cc +++ b/modules/audio_coding/neteq/neteq_impl.cc @@ -654,9 +654,13 @@ int NetEqImpl::InsertPacketInternal(const RTPHeader& rtp_header, } // Calculate the number of primary (non-FEC/RED) packets. - const int number_of_primary_packets = std::count_if( + const size_t number_of_primary_packets = std::count_if( parsed_packet_list.begin(), parsed_packet_list.end(), [](const Packet& in) { return in.priority.codec_level == 0; }); + if (number_of_primary_packets < parsed_packet_list.size()) { + stats_->SecondaryPacketsReceived(parsed_packet_list.size() - + number_of_primary_packets); + } // Insert packets in buffer. const int ret = packet_buffer_->InsertPacketList( @@ -763,7 +767,9 @@ int NetEqImpl::GetAudioInternal(AudioFrame* audio_frame, expand_uma_logger_.UpdateSampleCounter(lifetime_stats.concealed_samples, fs_hz_); speech_expand_uma_logger_.UpdateSampleCounter( - lifetime_stats.voice_concealed_samples, fs_hz_); + lifetime_stats.concealed_samples - + lifetime_stats.silent_concealed_samples, + fs_hz_); // Check for muted state. if (enable_muted_state_ && expand_->Muted() && packet_buffer_->Empty()) { diff --git a/modules/audio_coding/neteq/statistics_calculator.cc b/modules/audio_coding/neteq/statistics_calculator.cc index a0e9bca4b1..d0f37bc3fe 100644 --- a/modules/audio_coding/neteq/statistics_calculator.cc +++ b/modules/audio_coding/neteq/statistics_calculator.cc @@ -182,8 +182,8 @@ void StatisticsCalculator::ConcealedSamplesCorrection(int num_samples, // Store negative correction to subtract from future positive additions. // See also the function comment in the header file. concealed_samples_correction_ -= num_samples; - if (is_voice) { - voice_concealed_samples_correction_ -= num_samples; + if (!is_voice) { + silent_concealed_samples_correction_ -= num_samples; } return; } @@ -193,22 +193,25 @@ void StatisticsCalculator::ConcealedSamplesCorrection(int num_samples, concealed_samples_correction_ -= canceled_out; lifetime_stats_.concealed_samples += num_samples - canceled_out; - if (is_voice) { - const size_t voice_canceled_out = std::min( - static_cast(num_samples), voice_concealed_samples_correction_); - voice_concealed_samples_correction_ -= voice_canceled_out; - lifetime_stats_.voice_concealed_samples += num_samples - voice_canceled_out; + if (!is_voice) { + const size_t silent_canceled_out = std::min( + static_cast(num_samples), silent_concealed_samples_correction_); + silent_concealed_samples_correction_ -= silent_canceled_out; + lifetime_stats_.silent_concealed_samples += + num_samples - silent_canceled_out; } } void StatisticsCalculator::PreemptiveExpandedSamples(size_t num_samples) { 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) { accelerate_samples_ += num_samples; operations_and_state_.accelerate_samples += num_samples; + lifetime_stats_.removed_samples_for_acceleration += num_samples; } void StatisticsCalculator::AddZeros(size_t num_samples) { @@ -221,6 +224,11 @@ void StatisticsCalculator::PacketsDiscarded(size_t num_packets) { void StatisticsCalculator::SecondaryPacketsDiscarded(size_t num_packets) { discarded_secondary_packets_ += num_packets; + lifetime_stats_.fec_packets_discarded += num_packets; +} + +void StatisticsCalculator::SecondaryPacketsReceived(size_t num_packets) { + lifetime_stats_.fec_packets_received += num_packets; } void StatisticsCalculator::LostSamples(size_t num_samples) { diff --git a/modules/audio_coding/neteq/statistics_calculator.h b/modules/audio_coding/neteq/statistics_calculator.h index cb92f37f8f..4482812a75 100644 --- a/modules/audio_coding/neteq/statistics_calculator.h +++ b/modules/audio_coding/neteq/statistics_calculator.h @@ -63,8 +63,11 @@ class StatisticsCalculator { // Reports that |num_packets| packets were discarded. virtual void PacketsDiscarded(size_t num_packets); - // Reports that |num_packets| packets samples were discarded. - virtual void SecondaryPacketsDiscarded(size_t num_samples); + // Reports that |num_packets| secondary (FEC) packets were discarded. + virtual void SecondaryPacketsDiscarded(size_t num_packets); + + // Reports that |num_packets| secondary (FEC) packets were received. + virtual void SecondaryPacketsReceived(size_t num_packets); // Reports that |num_samples| were lost. void LostSamples(size_t num_samples); @@ -191,7 +194,7 @@ class StatisticsCalculator { NetEqLifetimeStatistics lifetime_stats_; NetEqOperationsAndState operations_and_state_; size_t concealed_samples_correction_ = 0; - size_t voice_concealed_samples_correction_ = 0; + size_t silent_concealed_samples_correction_ = 0; size_t preemptive_samples_; size_t accelerate_samples_; size_t added_zero_samples_; diff --git a/modules/audio_coding/neteq/tools/neteq_stats_getter.cc b/modules/audio_coding/neteq/tools/neteq_stats_getter.cc index 291fc24890..91dd47c37d 100644 --- a/modules/audio_coding/neteq/tools/neteq_stats_getter.cc +++ b/modules/audio_coding/neteq/tools/neteq_stats_getter.cc @@ -57,16 +57,16 @@ void NetEqStatsGetter::AfterGetAudio(int64_t time_now_ms, last_stats_query_time_ms_ = time_now_ms; } + const auto voice_concealed_samples = + lifetime_stat.concealed_samples - lifetime_stat.silent_concealed_samples; if (current_concealment_event_ != lifetime_stat.concealment_events && - voice_concealed_samples_until_last_event_ < - lifetime_stat.voice_concealed_samples) { + voice_concealed_samples_until_last_event_ < voice_concealed_samples) { if (last_event_end_time_ms_ > 0) { // Do not account for the first event to avoid start of the call // skewing. ConcealmentEvent concealment_event; uint64_t last_event_voice_concealed_samples = - lifetime_stat.voice_concealed_samples - - voice_concealed_samples_until_last_event_; + voice_concealed_samples - voice_concealed_samples_until_last_event_; RTC_CHECK_GT(last_event_voice_concealed_samples, 0); concealment_event.duration_ms = last_event_voice_concealed_samples / (audio_frame.sample_rate_hz_ / 1000); @@ -74,12 +74,10 @@ void NetEqStatsGetter::AfterGetAudio(int64_t time_now_ms, concealment_event.time_from_previous_event_end_ms = time_now_ms - last_event_end_time_ms_; concealment_events_.emplace_back(concealment_event); - voice_concealed_samples_until_last_event_ = - lifetime_stat.voice_concealed_samples; + voice_concealed_samples_until_last_event_ = voice_concealed_samples; } last_event_end_time_ms_ = time_now_ms; - voice_concealed_samples_until_last_event_ = - lifetime_stat.voice_concealed_samples; + voice_concealed_samples_until_last_event_ = voice_concealed_samples; current_concealment_event_ = lifetime_stat.concealment_events; } diff --git a/modules/audio_coding/neteq/tools/neteq_test.cc b/modules/audio_coding/neteq/tools/neteq_test.cc index 97e71bf21f..8a6a94a52d 100644 --- a/modules/audio_coding/neteq/tools/neteq_test.cc +++ b/modules/audio_coding/neteq/tools/neteq_test.cc @@ -224,8 +224,10 @@ NetEqTest::SimulationStepResult NetEqTest::RunToNextGetAudio() { (out_frame.speech_type_ == AudioFrame::SpeechType::kPLCCNG); const bool cng = out_frame.speech_type_ == AudioFrame::SpeechType::kCNG; const bool voice_concealed = - lifetime_stats.voice_concealed_samples > - prev_lifetime_stats_.voice_concealed_samples; + (lifetime_stats.concealed_samples - + lifetime_stats.silent_concealed_samples) > + (prev_lifetime_stats_.concealed_samples - + prev_lifetime_stats_.silent_concealed_samples); *text_log_ << "GetAudio - wallclock: " << std::setw(5) << time_now_ms << ", delta wc: " << std::setw(4) << (input_->NextEventTime().value_or(time_now_ms) -