1 /*
2  *  Copyright (c) 2012 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 VIDEO_CALL_STATS_H_
12 #define VIDEO_CALL_STATS_H_
13 
14 #include <list>
15 #include <memory>
16 
17 #include "modules/include/module.h"
18 #include "modules/include/module_common_types.h"
19 #include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
20 #include "rtc_base/constructor_magic.h"
21 #include "rtc_base/synchronization/mutex.h"
22 #include "rtc_base/thread_checker.h"
23 #include "system_wrappers/include/clock.h"
24 
25 namespace webrtc {
26 
27 // CallStats keeps track of statistics for a call.
28 // TODO(webrtc:11489): Make call_stats_ not depend on ProcessThread and
29 // make callbacks on the worker thread (TQ).
30 class CallStats : public Module, public RtcpRttStats {
31  public:
32   // Time interval for updating the observers.
33   static constexpr int64_t kUpdateIntervalMs = 1000;
34 
35   CallStats(Clock* clock, ProcessThread* process_thread);
36   ~CallStats() override;
37 
38   // Registers/deregisters a new observer to receive statistics updates.
39   // Must be called from the construction thread.
40   void RegisterStatsObserver(CallStatsObserver* observer);
41   void DeregisterStatsObserver(CallStatsObserver* observer);
42 
43   // Expose |LastProcessedRtt()| from RtcpRttStats to the public interface, as
44   // it is the part of the API that is needed by direct users of CallStats.
45   // TODO(tommi): Threading or lifetime guarantees are not explicit in how
46   // CallStats is used as RtcpRttStats or how pointers are cached in a
47   // few different places (distributed via Call). It would be good to clarify
48   // from what thread/TQ calls to OnRttUpdate and LastProcessedRtt need to be
49   // allowed.
50   int64_t LastProcessedRtt() const override;
51 
52   // Exposed for tests to test histogram support.
UpdateHistogramsForTest()53   void UpdateHistogramsForTest() { UpdateHistograms(); }
54 
55   // Helper struct keeping track of the time a rtt value is reported.
56   struct RttTime {
RttTimeRttTime57     RttTime(int64_t new_rtt, int64_t rtt_time) : rtt(new_rtt), time(rtt_time) {}
58     const int64_t rtt;
59     const int64_t time;
60   };
61 
62  private:
63   // RtcpRttStats implementation.
64   void OnRttUpdate(int64_t rtt) override;
65 
66   // Implements Module, to use the process thread.
67   int64_t TimeUntilNextProcess() override;
68   void Process() override;
69 
70   // TODO(tommi): Use this to know when we're attached to the process thread?
71   // Alternatively, inject that pointer via the ctor since the call_stats
72   // test code, isn't using a processthread atm.
73   void ProcessThreadAttached(ProcessThread* process_thread) override;
74 
75   // This method must only be called when the process thread is not
76   // running, and from the construction thread.
77   void UpdateHistograms();
78 
79   Clock* const clock_;
80 
81   // The last time 'Process' resulted in statistic update.
82   int64_t last_process_time_ RTC_GUARDED_BY(process_thread_checker_);
83   // The last RTT in the statistics update (zero if there is no valid estimate).
84   int64_t max_rtt_ms_ RTC_GUARDED_BY(process_thread_checker_);
85 
86   // Accessed from random threads (seemingly). Consider atomic.
87   // |avg_rtt_ms_| is allowed to be read on the process thread without a lock.
88   // |avg_rtt_ms_lock_| must be held elsewhere for reading.
89   // |avg_rtt_ms_lock_| must be held on the process thread for writing.
90   int64_t avg_rtt_ms_;
91 
92   // Protects |avg_rtt_ms_|.
93   mutable Mutex avg_rtt_ms_lock_;
94 
95   // |sum_avg_rtt_ms_|, |num_avg_rtt_| and |time_of_first_rtt_ms_| are only used
96   // on the ProcessThread when running. When the Process Thread is not running,
97   // (and only then) they can be used in UpdateHistograms(), usually called from
98   // the dtor.
99   int64_t sum_avg_rtt_ms_ RTC_GUARDED_BY(process_thread_checker_);
100   int64_t num_avg_rtt_ RTC_GUARDED_BY(process_thread_checker_);
101   int64_t time_of_first_rtt_ms_ RTC_GUARDED_BY(process_thread_checker_);
102 
103   // All Rtt reports within valid time interval, oldest first.
104   std::list<RttTime> reports_ RTC_GUARDED_BY(process_thread_checker_);
105 
106   // Observers getting stats reports.
107   // When attached to ProcessThread, this is read-only. In order to allow
108   // modification, we detach from the process thread while the observer
109   // list is updated, to avoid races. This allows us to not require a lock
110   // for the observers_ list, which makes the most common case lock free.
111   std::list<CallStatsObserver*> observers_;
112 
113   rtc::ThreadChecker construction_thread_checker_;
114   rtc::ThreadChecker process_thread_checker_;
115   ProcessThread* const process_thread_;
116   bool process_thread_running_ RTC_GUARDED_BY(construction_thread_checker_);
117 
118   RTC_DISALLOW_COPY_AND_ASSIGN(CallStats);
119 };
120 
121 }  // namespace webrtc
122 
123 #endif  // VIDEO_CALL_STATS_H_
124