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 RTC_BASE_RATE_STATISTICS_H_
12 #define RTC_BASE_RATE_STATISTICS_H_
13 
14 #include <stddef.h>
15 #include <stdint.h>
16 
17 #include <deque>
18 #include <memory>
19 
20 #include "absl/types/optional.h"
21 #include "rtc_base/system/rtc_export.h"
22 
23 namespace webrtc {
24 
25 // Class to estimate rates based on counts in a sequence of 1-millisecond
26 // intervals.
27 
28 // This class uses int64 for all its numbers because some rates can be very
29 // high; for instance, a 20 Mbit/sec video stream can wrap a 32-bit byte
30 // counter in 14 minutes.
31 
32 // Note that timestamps used in Update(), Rate() and SetWindowSize() must never
33 // decrease for two consecutive calls.
34 // TODO(bugs.webrtc.org/11600): Migrate from int64_t to Timestamp.
35 
36 class RTC_EXPORT RateStatistics {
37  public:
38   static constexpr float kBpsScale = 8000.0f;
39 
40   // max_window_size_ms = Maximum window size in ms for the rate estimation.
41   //                      Initial window size is set to this, but may be changed
42   //                      to something lower by calling SetWindowSize().
43   // scale = coefficient to convert counts/ms to desired unit
44   //         ex: kBpsScale (8000) for bits/s if count represents bytes.
45   RateStatistics(int64_t max_window_size_ms, float scale);
46 
47   RateStatistics(const RateStatistics& other);
48 
49   RateStatistics(RateStatistics&& other);
50 
51   ~RateStatistics();
52 
53   // Reset instance to original state.
54   void Reset();
55 
56   // Update rate with a new data point, moving averaging window as needed.
57   void Update(int64_t count, int64_t now_ms);
58 
59   // Note that despite this being a const method, it still updates the internal
60   // state (moves averaging window), but it doesn't make any alterations that
61   // are observable from the other methods, as long as supplied timestamps are
62   // from a monotonic clock. Ie, it doesn't matter if this call moves the
63   // window, since any subsequent call to Update or Rate would still have moved
64   // the window as much or more.
65   absl::optional<int64_t> Rate(int64_t now_ms) const;
66 
67   // Update the size of the averaging window. The maximum allowed value for
68   // window_size_ms is max_window_size_ms as supplied in the constructor.
69   bool SetWindowSize(int64_t window_size_ms, int64_t now_ms);
70 
71  private:
72   void EraseOld(int64_t now_ms);
73 
74   struct Bucket {
75     explicit Bucket(int64_t timestamp);
76     int64_t sum;  // Sum of all samples in this bucket.
77     int num_samples;          // Number of samples in this bucket.
78     const int64_t timestamp;  // Timestamp this bucket corresponds to.
79   };
80   // All buckets within the time window, ordered by time.
81   std::deque<Bucket> buckets_;
82 
83   // Total count recorded in all buckets.
84   int64_t accumulated_count_;
85 
86   // Timestamp of the first data point seen, or -1 of none seen.
87   int64_t first_timestamp_;
88 
89   // True if accumulated_count_ has ever grown too large to be
90   // contained in its integer type.
91   bool overflow_ = false;
92 
93   // The total number of samples in the buckets.
94   int num_samples_;
95 
96   // To convert counts/ms to desired units
97   const float scale_;
98 
99   // The window sizes, in ms, over which the rate is calculated.
100   const int64_t max_window_size_ms_;
101   int64_t current_window_size_ms_;
102 };
103 }  // namespace webrtc
104 
105 #endif  // RTC_BASE_RATE_STATISTICS_H_
106