Implement newly standardized stats

Several new audio stats have been added to the standard, and this CL
implements those inside of NetEq. Exposing these metrics on the API will
be done in a follow-up CL.

Bug: webrtc:10442, webrtc:10443, webrtc:10444
Change-Id: Ia7aa5a6d76685fc0fdb446172a0a3fd0310f6cb7
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/133887
Reviewed-by: Minyue Li <minyue@webrtc.org>
Commit-Queue: Ivo Creusen <ivoc@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#27755}
diff --git a/modules/audio_coding/neteq/include/neteq.h b/modules/audio_coding/neteq/include/neteq.h
index 549d355..8721663 100644
--- a/modules/audio_coding/neteq/include/neteq.h
+++ b/modules/audio_coding/neteq/include/neteq.h
@@ -71,8 +71,12 @@
   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 b7f5579..fcb09be 100644
--- a/modules/audio_coding/neteq/neteq_impl.cc
+++ b/modules/audio_coding/neteq/neteq_impl.cc
@@ -654,9 +654,13 @@
   }
 
   // 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 @@
   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 a0e9bca..d0f37bc 100644
--- a/modules/audio_coding/neteq/statistics_calculator.cc
+++ b/modules/audio_coding/neteq/statistics_calculator.cc
@@ -182,8 +182,8 @@
     // 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 @@
   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<size_t>(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<size_t>(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::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 cb92f37..4482812 100644
--- a/modules/audio_coding/neteq/statistics_calculator.h
+++ b/modules/audio_coding/neteq/statistics_calculator.h
@@ -63,8 +63,11 @@
   // 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 @@
   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 291fc24..91dd47c 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 @@
     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 @@
       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 97e71bf..8a6a94a 100644
--- a/modules/audio_coding/neteq/tools/neteq_test.cc
+++ b/modules/audio_coding/neteq/tools/neteq_test.cc
@@ -224,8 +224,10 @@
             (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) -