Chromium Code Reviews| 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 |