1 /*
2  *  Copyright (c) 2020 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_STATS2_H_
12 #define VIDEO_CALL_STATS2_H_
13 
14 #include <list>
15 #include <memory>
16 
17 #include "api/units/timestamp.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/sequence_checker.h"
22 #include "rtc_base/task_queue.h"
23 #include "rtc_base/task_utils/pending_task_safety_flag.h"
24 #include "rtc_base/task_utils/repeating_task.h"
25 #include "system_wrappers/include/clock.h"
26 
27 namespace webrtc {
28 namespace internal {
29 
30 class CallStats {
31  public:
32   // Time interval for updating the observers.
33   static constexpr TimeDelta kUpdateInterval = TimeDelta::Millis(1000);
34 
35   CallStats(Clock* clock, TaskQueueBase* task_queue);
36   ~CallStats();
37 
38   // Expose an RtcpRttStats implementation without inheriting from RtcpRttStats.
39   // That allows us to separate the threading model of how RtcpRttStats is
40   // used (mostly on a process thread) and how CallStats is used (mostly on
41   // the TQ/worker thread). Since for both cases, there is a LastProcessedRtt()
42   // method, this separation allows us to not need a lock for either.
AsRtcpRttStats()43   RtcpRttStats* AsRtcpRttStats() { return &rtcp_rtt_stats_impl_; }
44 
45   // Registers/deregisters a new observer to receive statistics updates.
46   // Must be called from the construction thread.
47   void RegisterStatsObserver(CallStatsObserver* observer);
48   void DeregisterStatsObserver(CallStatsObserver* observer);
49 
50   // Expose |LastProcessedRtt()| from RtcpRttStats to the public interface, as
51   // it is the part of the API that is needed by direct users of CallStats.
52   // TODO(tommi): Threading or lifetime guarantees are not explicit in how
53   // CallStats is used as RtcpRttStats or how pointers are cached in a
54   // few different places (distributed via Call). It would be good to clarify
55   // from what thread/TQ calls to OnRttUpdate and LastProcessedRtt need to be
56   // allowed.
57   int64_t LastProcessedRtt() const;
58 
59   // Exposed for tests to test histogram support.
UpdateHistogramsForTest()60   void UpdateHistogramsForTest() { UpdateHistograms(); }
61 
62   // Helper struct keeping track of the time a rtt value is reported.
63   struct RttTime {
RttTimeRttTime64     RttTime(int64_t new_rtt, int64_t rtt_time) : rtt(new_rtt), time(rtt_time) {}
65     const int64_t rtt;
66     const int64_t time;
67   };
68 
69  private:
70   // Part of the RtcpRttStats implementation. Called by RtcpRttStatsImpl.
71   void OnRttUpdate(int64_t rtt);
72 
73   void UpdateAndReport();
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   class RtcpRttStatsImpl : public RtcpRttStats {
80    public:
RtcpRttStatsImpl(CallStats * owner)81     explicit RtcpRttStatsImpl(CallStats* owner) : owner_(owner) {}
82     ~RtcpRttStatsImpl() override = default;
83 
84    private:
OnRttUpdate(int64_t rtt)85     void OnRttUpdate(int64_t rtt) override {
86       // For video send streams (video/video_send_stream.cc), the RtpRtcp module
87       // is currently created on a transport worker TaskQueue and not the worker
88       // thread - which is what happens in other cases. We should probably fix
89       // that so that the call consistently comes in on the right thread.
90       owner_->OnRttUpdate(rtt);
91     }
92 
LastProcessedRtt()93     int64_t LastProcessedRtt() const override {
94       // This call path shouldn't be used anymore. This impl is only for
95       // propagating the rtt from the RtpRtcp module, which does not call
96       // LastProcessedRtt(). Down the line we should consider removing
97       // LastProcessedRtt() and use the interface for event notifications only.
98       RTC_NOTREACHED() << "Legacy call path";
99       return 0;
100     }
101 
102     CallStats* const owner_;
103   } rtcp_rtt_stats_impl_{this};
104 
105   Clock* const clock_;
106 
107   // Used to regularly call UpdateAndReport().
108   RepeatingTaskHandle repeating_task_
109       RTC_GUARDED_BY(construction_thread_checker_);
110 
111   // The last RTT in the statistics update (zero if there is no valid estimate).
112   int64_t max_rtt_ms_ RTC_GUARDED_BY(construction_thread_checker_);
113 
114   // Last reported average RTT value.
115   int64_t avg_rtt_ms_ RTC_GUARDED_BY(construction_thread_checker_);
116 
117   // |sum_avg_rtt_ms_|, |num_avg_rtt_| and |time_of_first_rtt_ms_| are only used
118   // on the ProcessThread when running. When the Process Thread is not running,
119   // (and only then) they can be used in UpdateHistograms(), usually called from
120   // the dtor.
121   int64_t sum_avg_rtt_ms_ RTC_GUARDED_BY(construction_thread_checker_);
122   int64_t num_avg_rtt_ RTC_GUARDED_BY(construction_thread_checker_);
123   int64_t time_of_first_rtt_ms_ RTC_GUARDED_BY(construction_thread_checker_);
124 
125   // All Rtt reports within valid time interval, oldest first.
126   std::list<RttTime> reports_ RTC_GUARDED_BY(construction_thread_checker_);
127 
128   // Observers getting stats reports.
129   // When attached to ProcessThread, this is read-only. In order to allow
130   // modification, we detach from the process thread while the observer
131   // list is updated, to avoid races. This allows us to not require a lock
132   // for the observers_ list, which makes the most common case lock free.
133   std::list<CallStatsObserver*> observers_;
134 
135   SequenceChecker construction_thread_checker_;
136   SequenceChecker process_thread_checker_;
137   TaskQueueBase* const task_queue_;
138 
139   // Used to signal destruction to potentially pending tasks.
140   ScopedTaskSafety task_safety_;
141 
142   RTC_DISALLOW_COPY_AND_ASSIGN(CallStats);
143 };
144 
145 }  // namespace internal
146 }  // namespace webrtc
147 
148 #endif  // VIDEO_CALL_STATS2_H_
149