1 /*
2  *  Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 
11 #ifndef MODULES_AUDIO_CODING_NETEQ_STATISTICS_CALCULATOR_H_
12 #define MODULES_AUDIO_CODING_NETEQ_STATISTICS_CALCULATOR_H_
13 
14 #include <deque>
15 #include <string>
16 
17 #include "api/neteq/neteq.h"
18 #include "rtc_base/constructor_magic.h"
19 
20 namespace webrtc {
21 
22 class DelayManager;
23 
24 // This class handles various network statistics in NetEq.
25 class StatisticsCalculator {
26  public:
27   StatisticsCalculator();
28 
29   virtual ~StatisticsCalculator();
30 
31   // Resets most of the counters.
32   void Reset();
33 
34   // Resets the counters that are not handled by Reset().
35   void ResetMcu();
36 
37   // Reports that |num_samples| samples were produced through expansion, and
38   // that the expansion produced other than just noise samples.
39   void ExpandedVoiceSamples(size_t num_samples, bool is_new_concealment_event);
40 
41   // Reports that |num_samples| samples were produced through expansion, and
42   // that the expansion produced only noise samples.
43   void ExpandedNoiseSamples(size_t num_samples, bool is_new_concealment_event);
44 
45   // Corrects the statistics for number of samples produced through non-noise
46   // expansion by adding |num_samples| (negative or positive) to the current
47   // value. The result is capped to zero to avoid negative values.
48   void ExpandedVoiceSamplesCorrection(int num_samples);
49 
50   // Same as ExpandedVoiceSamplesCorrection but for noise samples.
51   void ExpandedNoiseSamplesCorrection(int num_samples);
52 
53   void DecodedOutputPlayed();
54 
55   // Mark end of expand event; triggers some stats to be reported.
56   void EndExpandEvent(int fs_hz);
57 
58   // Reports that |num_samples| samples were produced through preemptive
59   // expansion.
60   void PreemptiveExpandedSamples(size_t num_samples);
61 
62   // Reports that |num_samples| samples were removed through accelerate.
63   void AcceleratedSamples(size_t num_samples);
64 
65   // Reports that |num_samples| zeros were inserted into the output.
66   void AddZeros(size_t num_samples);
67 
68   // Reports that |num_packets| packets were discarded.
69   virtual void PacketsDiscarded(size_t num_packets);
70 
71   // Reports that |num_packets| secondary (FEC) packets were discarded.
72   virtual void SecondaryPacketsDiscarded(size_t num_packets);
73 
74   // Reports that |num_packets| secondary (FEC) packets were received.
75   virtual void SecondaryPacketsReceived(size_t num_packets);
76 
77   // Reports that |num_samples| were lost.
78   void LostSamples(size_t num_samples);
79 
80   // Increases the report interval counter with |num_samples| at a sample rate
81   // of |fs_hz|. This is how the StatisticsCalculator gets notified that current
82   // time is increasing.
83   void IncreaseCounter(size_t num_samples, int fs_hz);
84 
85   // Update jitter buffer delay counter.
86   void JitterBufferDelay(size_t num_samples,
87                          uint64_t waiting_time_ms,
88                          uint64_t target_delay_ms);
89 
90   // Stores new packet waiting time in waiting time statistics.
91   void StoreWaitingTime(int waiting_time_ms);
92 
93   // Reports that |num_samples| samples were decoded from secondary packets.
94   void SecondaryDecodedSamples(int num_samples);
95 
96   // Reports that the packet buffer was flushed.
97   void FlushedPacketBuffer();
98 
99   // Reports that the jitter buffer received a packet.
100   void ReceivedPacket();
101 
102   // Reports that a received packet was delayed by |delay_ms| milliseconds.
103   virtual void RelativePacketArrivalDelay(size_t delay_ms);
104 
105   // Logs a delayed packet outage event of |num_samples| expanded at a sample
106   // rate of |fs_hz|. A delayed packet outage event is defined as an expand
107   // period caused not by an actual packet loss, but by a delayed packet.
108   virtual void LogDelayedPacketOutageEvent(int num_samples, int fs_hz);
109 
110   // Returns the current network statistics in |stats|. The current sample rate
111   // is |fs_hz|, the total number of samples in packet buffer and sync buffer
112   // yet to play out is |num_samples_in_buffers|, and the number of samples per
113   // packet is |samples_per_packet|. The method does not populate
114   // |preferred_buffer_size_ms|, |jitter_peaks_found| or |clockdrift_ppm|; use
115   // the PopulateDelayManagerStats method for those.
116   void GetNetworkStatistics(int fs_hz,
117                             size_t num_samples_in_buffers,
118                             size_t samples_per_packet,
119                             NetEqNetworkStatistics* stats);
120 
121   // Returns a copy of this class's lifetime statistics. These statistics are
122   // never reset.
123   NetEqLifetimeStatistics GetLifetimeStatistics() const;
124 
125   NetEqOperationsAndState GetOperationsAndState() const;
126 
127  private:
128   static const int kMaxReportPeriod = 60;  // Seconds before auto-reset.
129   static const size_t kLenWaitingTimes = 100;
130 
131   class PeriodicUmaLogger {
132    public:
133     PeriodicUmaLogger(const std::string& uma_name,
134                       int report_interval_ms,
135                       int max_value);
136     virtual ~PeriodicUmaLogger();
137     void AdvanceClock(int step_ms);
138 
139    protected:
140     void LogToUma(int value) const;
141     virtual int Metric() const = 0;
142     virtual void Reset() = 0;
143 
144     const std::string uma_name_;
145     const int report_interval_ms_;
146     const int max_value_;
147     int timer_ = 0;
148   };
149 
150   class PeriodicUmaCount final : public PeriodicUmaLogger {
151    public:
152     PeriodicUmaCount(const std::string& uma_name,
153                      int report_interval_ms,
154                      int max_value);
155     ~PeriodicUmaCount() override;
156     void RegisterSample();
157 
158    protected:
159     int Metric() const override;
160     void Reset() override;
161 
162    private:
163     int counter_ = 0;
164   };
165 
166   class PeriodicUmaAverage final : public PeriodicUmaLogger {
167    public:
168     PeriodicUmaAverage(const std::string& uma_name,
169                        int report_interval_ms,
170                        int max_value);
171     ~PeriodicUmaAverage() override;
172     void RegisterSample(int value);
173 
174    protected:
175     int Metric() const override;
176     void Reset() override;
177 
178    private:
179     double sum_ = 0.0;
180     int counter_ = 0;
181   };
182 
183   // Corrects the concealed samples counter in lifetime_stats_. The value of
184   // num_samples_ is added directly to the stat if the correction is positive.
185   // If the correction is negative, it is cached and will be subtracted against
186   // future additions to the counter. This is meant to be called from
187   // Expanded{Voice,Noise}Samples{Correction}.
188   void ConcealedSamplesCorrection(int num_samples, bool is_voice);
189 
190   // Calculates numerator / denominator, and returns the value in Q14.
191   static uint16_t CalculateQ14Ratio(size_t numerator, uint32_t denominator);
192 
193   NetEqLifetimeStatistics lifetime_stats_;
194   NetEqOperationsAndState operations_and_state_;
195   size_t concealed_samples_correction_ = 0;
196   size_t silent_concealed_samples_correction_ = 0;
197   size_t preemptive_samples_;
198   size_t accelerate_samples_;
199   size_t added_zero_samples_;
200   size_t expanded_speech_samples_;
201   size_t expanded_noise_samples_;
202   size_t concealed_samples_at_event_end_ = 0;
203   size_t discarded_packets_;
204   size_t lost_timestamps_;
205   uint32_t timestamps_since_last_report_;
206   std::deque<int> waiting_times_;
207   uint32_t secondary_decoded_samples_;
208   size_t discarded_secondary_packets_;
209   PeriodicUmaCount delayed_packet_outage_counter_;
210   PeriodicUmaAverage excess_buffer_delay_;
211   PeriodicUmaCount buffer_full_counter_;
212   bool decoded_output_played_ = false;
213 
214   RTC_DISALLOW_COPY_AND_ASSIGN(StatisticsCalculator);
215 };
216 
217 }  // namespace webrtc
218 #endif  // MODULES_AUDIO_CODING_NETEQ_STATISTICS_CALCULATOR_H_
219