text: /*
   *  Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
   *
   *  Use of this source code is governed by a BSD-style license
   *  that can be found in the LICENSE file in the root of the source
   *  tree. An additional intellectual property rights grant can be found
   *  in the file PATENTS.  All contributing project authors may
   *  be found in the AUTHORS file in the root of the source tree.
   */
  
  #ifndef MODULES_AUDIO_CODING_NETEQ_STATISTICS_CALCULATOR_H_
  #define MODULES_AUDIO_CODING_NETEQ_STATISTICS_CALCULATOR_H_
  
  #include <deque>
  #include <string>
  
  #include "modules/audio_coding/neteq/include/neteq.h"
  #include "rtc_base/constructor_magic.h"
  
  namespace webrtc {
  
  class DelayManager;
  
  // This class handles various network statistics in NetEq.
  class StatisticsCalculator {
   public:
    StatisticsCalculator();
  
    virtual ~StatisticsCalculator();
  
    // Resets most of the counters.
    void Reset();
  
    // Resets the counters that are not handled by Reset().
    void ResetMcu();
  
    // Reports that |num_samples| samples were produced through expansion, and
    // that the expansion produced other than just noise samples.
    void ExpandedVoiceSamples(size_t num_samples, bool is_new_concealment_event);
  
    // Reports that |num_samples| samples were produced through expansion, and
    // that the expansion produced only noise samples.
    void ExpandedNoiseSamples(size_t num_samples, bool is_new_concealment_event);
  
    // Corrects the statistics for number of samples produced through non-noise
    // expansion by adding |num_samples| (negative or positive) to the current
    // value. The result is capped to zero to avoid negative values.
    void ExpandedVoiceSamplesCorrection(int num_samples);
  
    // Same as ExpandedVoiceSamplesCorrection but for noise samples.
    void ExpandedNoiseSamplesCorrection(int num_samples);
  
    // Reports that |num_samples| samples were produced through preemptive
    // expansion.
    void PreemptiveExpandedSamples(size_t num_samples);
  
    // Reports that |num_samples| samples were removed through accelerate.
    void AcceleratedSamples(size_t num_samples);
  
    // Reports that |num_samples| zeros were inserted into the output.
    void AddZeros(size_t num_samples);
  
    // Reports that |num_packets| packets were discarded.
    virtual void PacketsDiscarded(size_t num_packets);
  
    // 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);
  
    // Increases the report interval counter with |num_samples| at a sample rate
    // of |fs_hz|. This is how the StatisticsCalculator gets notified that current
    // time is increasing.
    void IncreaseCounter(size_t num_samples, int fs_hz);
  
    // Update jitter buffer delay counter.
    void JitterBufferDelay(size_t num_samples, uint64_t waiting_time_ms);
  
    // Stores new packet waiting time in waiting time statistics.
    void StoreWaitingTime(int waiting_time_ms);
  
    // Reports that |num_samples| samples were decoded from secondary packets.
    void SecondaryDecodedSamples(int num_samples);
  
    // Reports that the packet buffer was flushed.
    void FlushedPacketBuffer();
  
    // Reports that the jitter buffer received a packet.
    void ReceivedPacket();
  
    // Reports that a received packet was delayed by |delay_ms| milliseconds.
    virtual void RelativePacketArrivalDelay(size_t delay_ms);
  
    // Logs a delayed packet outage event of |num_samples| expanded at a sample
    // rate of |fs_hz|. A delayed packet outage event is defined as an expand
    // 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
    // |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,
                              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;
  
    NetEqOperationsAndState GetOperationsAndState() const;
  
   private:
    static const int kMaxReportPeriod = 60;  // Seconds before auto-reset.
    static const size_t kLenWaitingTimes = 100;
  
    class PeriodicUmaLogger {
     public:
      PeriodicUmaLogger(const std::string& uma_name,
                        int report_interval_ms,
                        int max_value);
      virtual ~PeriodicUmaLogger();
      void AdvanceClock(int step_ms);
  
     protected:
      void LogToUma(int value) const;
      virtual int Metric() const = 0;
      virtual void Reset() = 0;
  
      const std::string uma_name_;
      const int report_interval_ms_;
      const int max_value_;
      int timer_ = 0;
    };
  
    class PeriodicUmaCount final : public PeriodicUmaLogger {
     public:
      PeriodicUmaCount(const std::string& uma_name,
                       int report_interval_ms,
                       int max_value);
      ~PeriodicUmaCount() override;
      void RegisterSample();
  
     protected:
      int Metric() const override;
      void Reset() override;
  
     private:
      int counter_ = 0;
    };
  
    class PeriodicUmaAverage final : public PeriodicUmaLogger {
     public:
      PeriodicUmaAverage(const std::string& uma_name,
                         int report_interval_ms,
                         int max_value);
      ~PeriodicUmaAverage() override;
      void RegisterSample(int value);
  
     protected:
      int Metric() const override;
      void Reset() override;
  
     private:
      double sum_ = 0.0;
      int counter_ = 0;
    };
  
    // Corrects the concealed samples counter in lifetime_stats_. The value of
    // num_samples_ is added directly to the stat if the correction is positive.
    // If the correction is negative, it is cached and will be subtracted against
    // future additions to the counter. This is meant to be called from
    // Expanded{Voice,Noise}Samples{Correction}.
    void ConcealedSamplesCorrection(int num_samples, bool is_voice);
  
    // Calculates numerator / denominator, and returns the value in Q14.
    static uint16_t CalculateQ14Ratio(size_t numerator, uint32_t denominator);
  
    NetEqLifetimeStatistics lifetime_stats_;
    NetEqOperationsAndState operations_and_state_;
    size_t concealed_samples_correction_ = 0;
    size_t silent_concealed_samples_correction_ = 0;
    size_t preemptive_samples_;
    size_t accelerate_samples_;
    size_t added_zero_samples_;
    size_t expanded_speech_samples_;
    size_t expanded_noise_samples_;
    size_t discarded_packets_;
    size_t lost_timestamps_;
    uint32_t timestamps_since_last_report_;
    std::deque<int> waiting_times_;
    uint32_t secondary_decoded_samples_;
    size_t discarded_secondary_packets_;
    PeriodicUmaCount delayed_packet_outage_counter_;
    PeriodicUmaAverage excess_buffer_delay_;
    PeriodicUmaCount buffer_full_counter_;
  
    RTC_DISALLOW_COPY_AND_ASSIGN(StatisticsCalculator);
  };
  
  }  // namespace webrtc
  #endif  // MODULES_AUDIO_CODING_NETEQ_STATISTICS_CALCULATOR_H_
  