OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright 2016 The WebRTC Project Authors. All rights reserved. | 2 * Copyright 2016 The WebRTC Project Authors. All rights reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 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 | 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 | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 | 10 |
11 #include "webrtc/stats/rtcstatscollector.h" | 11 #include "webrtc/stats/rtcstatscollector.h" |
12 | 12 |
13 #include <memory> | 13 #include <memory> |
14 #include <utility> | 14 #include <utility> |
15 #include <vector> | 15 #include <vector> |
16 | 16 |
17 #include "webrtc/api/peerconnection.h" | 17 #include "webrtc/api/peerconnection.h" |
18 #include "webrtc/base/checks.h" | 18 #include "webrtc/base/checks.h" |
19 | 19 |
20 namespace webrtc { | 20 namespace webrtc { |
21 | 21 |
22 rtc::scoped_refptr<RTCStatsCollector> RTCStatsCollector::Create( | |
23 PeerConnection* pc, | |
24 double cache_lifetime, | |
25 std::unique_ptr<rtc::Timing> timing) { | |
26 return rtc::scoped_refptr<RTCStatsCollector>( | |
27 new rtc::RefCountedObject<RTCStatsCollector>( | |
28 pc, cache_lifetime, timing.release())); | |
29 } | |
30 | |
22 RTCStatsCollector::RTCStatsCollector( | 31 RTCStatsCollector::RTCStatsCollector( |
23 PeerConnection* pc, | 32 PeerConnection* pc, |
24 double cache_lifetime, | 33 double cache_lifetime, |
25 std::unique_ptr<rtc::Timing> timing) | 34 rtc::Timing* timing) |
26 : pc_(pc), | 35 : pc_(pc), |
27 timing_(std::move(timing)), | 36 signaling_thread_(pc->session()->signaling_thread()), |
37 worker_thread_(pc->session()->worker_thread()), | |
38 network_thread_(pc->session()->network_thread()), | |
39 num_pending_partial_reports_(0), | |
40 timing_(timing), | |
28 cache_timestamp_(0.0), | 41 cache_timestamp_(0.0), |
29 cache_lifetime_(cache_lifetime) { | 42 cache_lifetime_(cache_lifetime) { |
30 RTC_DCHECK(pc_); | 43 RTC_DCHECK(pc_); |
44 RTC_DCHECK(signaling_thread_); | |
45 RTC_DCHECK(worker_thread_); | |
46 RTC_DCHECK(network_thread_); | |
31 RTC_DCHECK(timing_); | 47 RTC_DCHECK(timing_); |
32 RTC_DCHECK(IsOnSignalingThread()); | |
33 RTC_DCHECK_GE(cache_lifetime_, 0.0); | 48 RTC_DCHECK_GE(cache_lifetime_, 0.0); |
34 } | 49 } |
35 | 50 |
36 rtc::scoped_refptr<const RTCStatsReport> RTCStatsCollector::GetStatsReport() { | 51 void RTCStatsCollector::GetStatsReport( |
37 RTC_DCHECK(IsOnSignalingThread()); | 52 rtc::scoped_refptr<RTCStatsCollectorCallback> callback) { |
38 double now = timing_->TimerNow(); | 53 RTC_DCHECK(signaling_thread_->IsCurrent()); |
39 if (cached_report_ && now - cache_timestamp_ <= cache_lifetime_) | 54 RTC_DCHECK(callback); |
40 return cached_report_; | 55 rtc::scoped_refptr<const RTCStatsReport> cached_report; |
41 cache_timestamp_ = now; | 56 std::vector<rtc::scoped_refptr<RTCStatsCollectorCallback>> callbacks; |
42 | 57 { |
43 rtc::scoped_refptr<RTCStatsReport> report = RTCStatsReport::Create(); | 58 rtc::CritScope cs(&lock_); |
44 report->AddStats(ProducePeerConnectionStats()); | 59 callbacks_.push_back(callback); |
45 | 60 double now = timing_->TimerNow(); |
46 cached_report_ = report; | 61 if (cached_report_ && now - cache_timestamp_ <= cache_lifetime_) { |
47 return cached_report_; | 62 // We have a fresh cached report to immediately deliver. |
63 cached_report = cached_report_; | |
64 callbacks = callbacks_; | |
hta-webrtc
2016/08/31 09:57:36
So you use "callbacks" to pass the list of callbac
hbos
2016/09/01 14:16:16
Ah, only |num_pending_partial_reports_| and |parti
| |
65 callbacks_.clear(); | |
66 } else if (!num_pending_partial_reports_) { | |
67 // We don't have a fresh cached report and we are not already in the | |
68 // process of gathering stats. | |
69 num_pending_partial_reports_ = 3; | |
70 invoker_.AsyncInvoke<void>(RTC_FROM_HERE, signaling_thread_, | |
71 rtc::Bind( | |
72 &RTCStatsCollector::ProducePartialResultsOnSignalingThread_s, | |
73 rtc::scoped_refptr<RTCStatsCollector>(this), now)); | |
74 invoker_.AsyncInvoke<void>(RTC_FROM_HERE, worker_thread_, | |
75 rtc::Bind(&RTCStatsCollector::ProducePartialResultsOnWorkerThread_w, | |
76 rtc::scoped_refptr<RTCStatsCollector>(this), now)); | |
77 invoker_.AsyncInvoke<void>(RTC_FROM_HERE, network_thread_, | |
78 rtc::Bind(&RTCStatsCollector::ProducePartialResultsOnNetworkThread_n, | |
79 rtc::scoped_refptr<RTCStatsCollector>(this), now)); | |
80 } | |
hta-webrtc
2016/08/31 09:57:36
Where's the "else" branch (the report isn't fresh
hbos
2016/09/01 14:16:16
callback_ has been added to callbacks_ and will be
| |
81 } | |
82 // Do we have a cached report that is still fresh to deliver? | |
83 // Then do so without holding the lock. | |
84 if (cached_report) { | |
85 for (const rtc::scoped_refptr<RTCStatsCollectorCallback>& callback : | |
86 callbacks) { | |
87 callback->OnStatsDelivered(cached_report); | |
88 } | |
89 return; | |
90 } | |
48 } | 91 } |
49 | 92 |
50 void RTCStatsCollector::ClearCachedStatsReport() { | 93 void RTCStatsCollector::ClearCachedStatsReport() { |
51 RTC_DCHECK(IsOnSignalingThread()); | 94 RTC_DCHECK(signaling_thread_->IsCurrent()); |
95 rtc::CritScope cs(&lock_); | |
52 cached_report_ = nullptr; | 96 cached_report_ = nullptr; |
53 } | 97 } |
54 | 98 |
55 bool RTCStatsCollector::IsOnSignalingThread() const { | 99 void RTCStatsCollector::ProducePartialResultsOnSignalingThread_s( |
56 return pc_->session()->signaling_thread()->IsCurrent(); | 100 double timestamp) { |
101 RTC_DCHECK(signaling_thread_->IsCurrent()); | |
102 rtc::scoped_refptr<RTCStatsReport> report = RTCStatsReport::Create(); | |
103 | |
104 report->AddStats(ProducePeerConnectionStats_s(timestamp)); | |
105 | |
106 AddPartialResults(report, timestamp); | |
107 } | |
108 | |
109 void RTCStatsCollector::ProducePartialResultsOnWorkerThread_w( | |
110 double timestamp) { | |
111 RTC_DCHECK(worker_thread_->IsCurrent()); | |
112 rtc::scoped_refptr<RTCStatsReport> report = RTCStatsReport::Create(); | |
113 | |
114 // TODO(hbos): Gather stats on worker thread. | |
115 | |
116 AddPartialResults(report, timestamp); | |
117 } | |
118 | |
119 void RTCStatsCollector::ProducePartialResultsOnNetworkThread_n( | |
120 double timestamp) { | |
121 RTC_DCHECK(network_thread_->IsCurrent()); | |
122 rtc::scoped_refptr<RTCStatsReport> report = RTCStatsReport::Create(); | |
123 | |
124 // TODO(hbos): Gather stats on network thread. | |
125 | |
126 AddPartialResults(report, timestamp); | |
127 } | |
128 | |
129 void RTCStatsCollector::AddPartialResults( | |
130 const rtc::scoped_refptr<RTCStatsReport>& partial_report, | |
131 double timestamp) { | |
132 if (!signaling_thread_->IsCurrent()) { | |
133 invoker_.AsyncInvoke<void>(RTC_FROM_HERE, signaling_thread_, | |
134 rtc::Bind(&RTCStatsCollector::AddPartialResults_s, | |
135 rtc::scoped_refptr<RTCStatsCollector>(this), | |
136 partial_report, timestamp)); | |
137 return; | |
138 } | |
139 AddPartialResults_s(partial_report, timestamp); | |
140 } | |
141 | |
142 void RTCStatsCollector::AddPartialResults_s( | |
143 rtc::scoped_refptr<RTCStatsReport> partial_report, double timestamp) { | |
144 RTC_DCHECK(signaling_thread_->IsCurrent()); | |
145 rtc::scoped_refptr<const RTCStatsReport> result; | |
146 std::vector<rtc::scoped_refptr<RTCStatsCollectorCallback>> callbacks; | |
147 { | |
148 rtc::CritScope cs(&lock_); | |
149 RTC_DCHECK_GT(num_pending_partial_reports_, 0); | |
150 if (!partial_report_) | |
151 partial_report_ = partial_report; | |
152 else | |
153 partial_report_->TakeMembersFrom(partial_report); | |
154 --num_pending_partial_reports_; | |
155 | |
156 // Was this the last pending partial report, resulting in a complete and | |
157 // deliverable |result|? | |
158 if (!num_pending_partial_reports_) { | |
159 result = cached_report_ = partial_report_; | |
160 cache_timestamp_ = timestamp; | |
161 partial_report_ = nullptr; | |
162 callbacks = callbacks_; | |
163 callbacks_.clear(); | |
164 } | |
165 } | |
166 // Do we have a report to deliver? Then do so without holding the lock. | |
167 if (result) { | |
168 for (const rtc::scoped_refptr<RTCStatsCollectorCallback>& callback : | |
169 callbacks) { | |
170 callback->OnStatsDelivered(result); | |
171 } | |
172 } | |
57 } | 173 } |
58 | 174 |
59 std::unique_ptr<RTCPeerConnectionStats> | 175 std::unique_ptr<RTCPeerConnectionStats> |
60 RTCStatsCollector::ProducePeerConnectionStats() const { | 176 RTCStatsCollector::ProducePeerConnectionStats_s(double timestamp) const { |
177 RTC_DCHECK(signaling_thread_->IsCurrent()); | |
61 // TODO(hbos): If data channels are removed from the peer connection this will | 178 // TODO(hbos): If data channels are removed from the peer connection this will |
62 // yield incorrect counts. Address before closing crbug.com/636818. See | 179 // yield incorrect counts. Address before closing crbug.com/636818. See |
63 // https://w3c.github.io/webrtc-stats/webrtc-stats.html#pcstats-dict*. | 180 // https://w3c.github.io/webrtc-stats/webrtc-stats.html#pcstats-dict*. |
64 uint32_t data_channels_opened = 0; | 181 uint32_t data_channels_opened = 0; |
65 const std::vector<rtc::scoped_refptr<DataChannel>>& data_channels = | 182 const std::vector<rtc::scoped_refptr<DataChannel>>& data_channels = |
66 pc_->sctp_data_channels(); | 183 pc_->sctp_data_channels(); |
67 for (const rtc::scoped_refptr<DataChannel>& data_channel : data_channels) { | 184 for (const rtc::scoped_refptr<DataChannel>& data_channel : data_channels) { |
68 if (data_channel->state() == DataChannelInterface::kOpen) | 185 if (data_channel->state() == DataChannelInterface::kOpen) |
69 ++data_channels_opened; | 186 ++data_channels_opened; |
70 } | 187 } |
71 // There is always just one |RTCPeerConnectionStats| so its |id| can be a | 188 // There is always just one |RTCPeerConnectionStats| so its |id| can be a |
72 // constant. | 189 // constant. |
73 std::unique_ptr<RTCPeerConnectionStats> stats( | 190 std::unique_ptr<RTCPeerConnectionStats> stats( |
74 new RTCPeerConnectionStats("RTCPeerConnection", cache_timestamp_)); | 191 new RTCPeerConnectionStats("RTCPeerConnection", timestamp)); |
75 stats->data_channels_opened = data_channels_opened; | 192 stats->data_channels_opened = data_channels_opened; |
76 stats->data_channels_closed = static_cast<uint32_t>(data_channels.size()) - | 193 stats->data_channels_closed = static_cast<uint32_t>(data_channels.size()) - |
77 data_channels_opened; | 194 data_channels_opened; |
78 return stats; | 195 return stats; |
79 } | 196 } |
80 | 197 |
81 } // namespace webrtc | 198 } // namespace webrtc |
OLD | NEW |