Fix standard GetStats to not modify NetEq state.

Add a get_and_clear_legacy_stats flag to AudioReceiveStream::GetStats,
to distinguish calls from standard GetStats and legacy GetStats.

Add const method NetEq::CurrentNetworkStatistics to get current
values of stateless NetEq stats. Standard GetStats will then call this
method instead of NetEq::NetworkStatistics.

Bug: webrtc:11622
Change-Id: I3833a246a9e39b18c99657a738da22c6e2bd5f5e
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/183600
Commit-Queue: Niels Moller <nisse@webrtc.org>
Reviewed-by: Henrik Boström <hbos@webrtc.org>
Reviewed-by: Karl Wiberg <kwiberg@webrtc.org>
Reviewed-by: Ivo Creusen <ivoc@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#32092}
diff --git a/modules/audio_coding/acm2/acm_receiver.cc b/modules/audio_coding/acm2/acm_receiver.cc
index 33142c7..5600883 100644
--- a/modules/audio_coding/acm2/acm_receiver.cc
+++ b/modules/audio_coding/acm2/acm_receiver.cc
@@ -244,26 +244,45 @@
   return std::make_pair(last_decoder_->payload_type, last_decoder_->sdp_format);
 }
 
-void AcmReceiver::GetNetworkStatistics(NetworkStatistics* acm_stat) const {
+void AcmReceiver::GetNetworkStatistics(
+    NetworkStatistics* acm_stat,
+    bool get_and_clear_legacy_stats /* = true */) const {
   NetEqNetworkStatistics neteq_stat;
-  // NetEq function always returns zero, so we don't check the return value.
-  neteq_->NetworkStatistics(&neteq_stat);
+  if (get_and_clear_legacy_stats) {
+    // NetEq function always returns zero, so we don't check the return value.
+    neteq_->NetworkStatistics(&neteq_stat);
 
+    acm_stat->currentPacketLossRate = neteq_stat.packet_loss_rate;
+    acm_stat->currentExpandRate = neteq_stat.expand_rate;
+    acm_stat->currentSpeechExpandRate = neteq_stat.speech_expand_rate;
+    acm_stat->currentPreemptiveRate = neteq_stat.preemptive_rate;
+    acm_stat->currentAccelerateRate = neteq_stat.accelerate_rate;
+    acm_stat->currentSecondaryDecodedRate = neteq_stat.secondary_decoded_rate;
+    acm_stat->currentSecondaryDiscardedRate =
+        neteq_stat.secondary_discarded_rate;
+    acm_stat->addedSamples = neteq_stat.added_zero_samples;
+    acm_stat->meanWaitingTimeMs = neteq_stat.mean_waiting_time_ms;
+    acm_stat->medianWaitingTimeMs = neteq_stat.median_waiting_time_ms;
+    acm_stat->minWaitingTimeMs = neteq_stat.min_waiting_time_ms;
+    acm_stat->maxWaitingTimeMs = neteq_stat.max_waiting_time_ms;
+  } else {
+    neteq_stat = neteq_->CurrentNetworkStatistics();
+    acm_stat->currentPacketLossRate = 0;
+    acm_stat->currentExpandRate = 0;
+    acm_stat->currentSpeechExpandRate = 0;
+    acm_stat->currentPreemptiveRate = 0;
+    acm_stat->currentAccelerateRate = 0;
+    acm_stat->currentSecondaryDecodedRate = 0;
+    acm_stat->currentSecondaryDiscardedRate = 0;
+    acm_stat->addedSamples = 0;
+    acm_stat->meanWaitingTimeMs = -1;
+    acm_stat->medianWaitingTimeMs = -1;
+    acm_stat->minWaitingTimeMs = -1;
+    acm_stat->maxWaitingTimeMs = 1;
+  }
   acm_stat->currentBufferSize = neteq_stat.current_buffer_size_ms;
   acm_stat->preferredBufferSize = neteq_stat.preferred_buffer_size_ms;
   acm_stat->jitterPeaksFound = neteq_stat.jitter_peaks_found ? true : false;
-  acm_stat->currentPacketLossRate = neteq_stat.packet_loss_rate;
-  acm_stat->currentExpandRate = neteq_stat.expand_rate;
-  acm_stat->currentSpeechExpandRate = neteq_stat.speech_expand_rate;
-  acm_stat->currentPreemptiveRate = neteq_stat.preemptive_rate;
-  acm_stat->currentAccelerateRate = neteq_stat.accelerate_rate;
-  acm_stat->currentSecondaryDecodedRate = neteq_stat.secondary_decoded_rate;
-  acm_stat->currentSecondaryDiscardedRate = neteq_stat.secondary_discarded_rate;
-  acm_stat->addedSamples = neteq_stat.added_zero_samples;
-  acm_stat->meanWaitingTimeMs = neteq_stat.mean_waiting_time_ms;
-  acm_stat->medianWaitingTimeMs = neteq_stat.median_waiting_time_ms;
-  acm_stat->minWaitingTimeMs = neteq_stat.min_waiting_time_ms;
-  acm_stat->maxWaitingTimeMs = neteq_stat.max_waiting_time_ms;
 
   NetEqLifetimeStatistics neteq_lifetime_stat = neteq_->GetLifetimeStatistics();
   acm_stat->totalSamplesReceived = neteq_lifetime_stat.total_samples_received;
diff --git a/modules/audio_coding/acm2/acm_receiver.h b/modules/audio_coding/acm2/acm_receiver.h
index d451a94..19dc577 100644
--- a/modules/audio_coding/acm2/acm_receiver.h
+++ b/modules/audio_coding/acm2/acm_receiver.h
@@ -138,7 +138,8 @@
   // Output:
   //   - statistics           : The current network statistics.
   //
-  void GetNetworkStatistics(NetworkStatistics* statistics) const;
+  void GetNetworkStatistics(NetworkStatistics* statistics,
+                            bool get_and_clear_legacy_stats = true) const;
 
   //
   // Flushes the NetEq packet and speech buffers.
diff --git a/modules/audio_coding/neteq/neteq_impl.cc b/modules/audio_coding/neteq/neteq_impl.cc
index 643fb1e..ef04062 100644
--- a/modules/audio_coding/neteq/neteq_impl.cc
+++ b/modules/audio_coding/neteq/neteq_impl.cc
@@ -387,17 +387,9 @@
 int NetEqImpl::NetworkStatistics(NetEqNetworkStatistics* stats) {
   MutexLock lock(&mutex_);
   assert(decoder_database_.get());
-  const size_t total_samples_in_buffers =
-      packet_buffer_->NumSamplesInBuffer(decoder_frame_length_) +
-      sync_buffer_->FutureLength();
-  assert(controller_.get());
-  stats->preferred_buffer_size_ms = controller_->TargetLevelMs();
-  stats->jitter_peaks_found = controller_->PeakFound();
-  stats_->GetNetworkStatistics(fs_hz_, total_samples_in_buffers,
-                               decoder_frame_length_, stats);
+  *stats = CurrentNetworkStatisticsInternal();
+  stats_->GetNetworkStatistics(decoder_frame_length_, stats);
   // Compensate for output delay chain.
-  stats->current_buffer_size_ms += output_delay_chain_ms_;
-  stats->preferred_buffer_size_ms += output_delay_chain_ms_;
   stats->mean_waiting_time_ms += output_delay_chain_ms_;
   stats->median_waiting_time_ms += output_delay_chain_ms_;
   stats->min_waiting_time_ms += output_delay_chain_ms_;
@@ -405,6 +397,31 @@
   return 0;
 }
 
+NetEqNetworkStatistics NetEqImpl::CurrentNetworkStatistics() const {
+  MutexLock lock(&mutex_);
+  return CurrentNetworkStatisticsInternal();
+}
+
+NetEqNetworkStatistics NetEqImpl::CurrentNetworkStatisticsInternal() const {
+  assert(decoder_database_.get());
+  NetEqNetworkStatistics stats;
+  const size_t total_samples_in_buffers =
+      packet_buffer_->NumSamplesInBuffer(decoder_frame_length_) +
+      sync_buffer_->FutureLength();
+
+  assert(controller_.get());
+  stats.preferred_buffer_size_ms = controller_->TargetLevelMs();
+  stats.jitter_peaks_found = controller_->PeakFound();
+  RTC_DCHECK_GT(fs_hz_, 0);
+  stats.current_buffer_size_ms =
+      static_cast<uint16_t>(total_samples_in_buffers * 1000 / fs_hz_);
+
+  // Compensate for output delay chain.
+  stats.current_buffer_size_ms += output_delay_chain_ms_;
+  stats.preferred_buffer_size_ms += output_delay_chain_ms_;
+  return stats;
+}
+
 NetEqLifetimeStatistics NetEqImpl::GetLifetimeStatistics() const {
   MutexLock lock(&mutex_);
   return stats_->GetLifetimeStatistics();
diff --git a/modules/audio_coding/neteq/neteq_impl.h b/modules/audio_coding/neteq/neteq_impl.h
index 0ade6b5..e130422 100644
--- a/modules/audio_coding/neteq/neteq_impl.h
+++ b/modules/audio_coding/neteq/neteq_impl.h
@@ -162,6 +162,8 @@
   // after the call.
   int NetworkStatistics(NetEqNetworkStatistics* stats) override;
 
+  NetEqNetworkStatistics CurrentNetworkStatistics() const override;
+
   NetEqLifetimeStatistics GetLifetimeStatistics() const override;
 
   NetEqOperationsAndState GetOperationsAndState() const override;
@@ -330,6 +332,9 @@
   virtual void UpdatePlcComponents(int fs_hz, size_t channels)
       RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
 
+  NetEqNetworkStatistics CurrentNetworkStatisticsInternal() const
+      RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
+
   Clock* const clock_;
 
   mutable Mutex mutex_;
diff --git a/modules/audio_coding/neteq/statistics_calculator.cc b/modules/audio_coding/neteq/statistics_calculator.cc
index cd9ea09..4c8491d 100644
--- a/modules/audio_coding/neteq/statistics_calculator.cc
+++ b/modules/audio_coding/neteq/statistics_calculator.cc
@@ -312,16 +312,11 @@
   operations_and_state_.last_waiting_time_ms = waiting_time_ms;
 }
 
-void StatisticsCalculator::GetNetworkStatistics(int fs_hz,
-                                                size_t num_samples_in_buffers,
-                                                size_t samples_per_packet,
+void StatisticsCalculator::GetNetworkStatistics(size_t samples_per_packet,
                                                 NetEqNetworkStatistics* stats) {
-  RTC_DCHECK_GT(fs_hz, 0);
   RTC_DCHECK(stats);
 
   stats->added_zero_samples = 0;
-  stats->current_buffer_size_ms =
-      static_cast<uint16_t>(num_samples_in_buffers * 1000 / fs_hz);
 
   stats->packet_loss_rate =
       CalculateQ14Ratio(lost_timestamps_, timestamps_since_last_report_);
diff --git a/modules/audio_coding/neteq/statistics_calculator.h b/modules/audio_coding/neteq/statistics_calculator.h
index 4dfe200..6ed5164 100644
--- a/modules/audio_coding/neteq/statistics_calculator.h
+++ b/modules/audio_coding/neteq/statistics_calculator.h
@@ -104,15 +104,11 @@
   // period caused not by an actual packet loss, but by a delayed packet.
   virtual void LogDelayedPacketOutageEvent(int num_samples, int fs_hz);
 
-  // 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|. The method does not populate
+  // Returns the current network statistics in |stats|. The number of samples
+  // per 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,
+  void GetNetworkStatistics(size_t samples_per_packet,
                             NetEqNetworkStatistics* stats);
 
   // Returns a copy of this class's lifetime statistics. These statistics are
diff --git a/modules/audio_coding/neteq/statistics_calculator_unittest.cc b/modules/audio_coding/neteq/statistics_calculator_unittest.cc
index abfa3c5..e6a9c26 100644
--- a/modules/audio_coding/neteq/statistics_calculator_unittest.cc
+++ b/modules/audio_coding/neteq/statistics_calculator_unittest.cc
@@ -70,14 +70,11 @@
   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);
+  stats.GetNetworkStatistics(kSamplesPerPacket, &stats_output);
 
   EXPECT_EQ(0u, stats_output.expand_rate);
   EXPECT_EQ(0u, stats_output.speech_expand_rate);
@@ -86,8 +83,7 @@
   stats.ExpandedVoiceSamplesCorrection(-100);
   stats.ExpandedNoiseSamplesCorrection(-100);
   stats.IncreaseCounter(k10MsSamples, kSampleRateHz);
-  stats.GetNetworkStatistics(kSampleRateHz, kNumSamplesInBuffer,
-                             kSamplesPerPacket, &stats_output);
+  stats.GetNetworkStatistics(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);
@@ -96,8 +92,7 @@
   stats.ExpandedVoiceSamplesCorrection(50);
   stats.ExpandedNoiseSamplesCorrection(200);
   stats.IncreaseCounter(k10MsSamples, kSampleRateHz);
-  stats.GetNetworkStatistics(kSampleRateHz, kNumSamplesInBuffer,
-                             kSamplesPerPacket, &stats_output);
+  stats.GetNetworkStatistics(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);