OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "remoting/protocol/performance_tracker.h" | 5 #include "remoting/protocol/performance_tracker.h" |
6 | 6 |
7 #include "remoting/protocol/frame_stats.h" | 7 #include "remoting/protocol/frame_stats.h" |
8 | 8 |
9 namespace { | 9 namespace { |
10 | 10 |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
100 UpdateUmaEnumHistogramCallback update_uma_enum_histogram_callback) { | 100 UpdateUmaEnumHistogramCallback update_uma_enum_histogram_callback) { |
101 DCHECK(!update_uma_custom_counts_callback.is_null()); | 101 DCHECK(!update_uma_custom_counts_callback.is_null()); |
102 DCHECK(!update_uma_custom_times_callback.is_null()); | 102 DCHECK(!update_uma_custom_times_callback.is_null()); |
103 DCHECK(!update_uma_enum_histogram_callback.is_null()); | 103 DCHECK(!update_uma_enum_histogram_callback.is_null()); |
104 | 104 |
105 uma_custom_counts_updater_ = update_uma_custom_counts_callback; | 105 uma_custom_counts_updater_ = update_uma_custom_counts_callback; |
106 uma_custom_times_updater_ = update_uma_custom_times_callback; | 106 uma_custom_times_updater_ = update_uma_custom_times_callback; |
107 uma_enum_histogram_updater_ = update_uma_enum_histogram_callback; | 107 uma_enum_histogram_updater_ = update_uma_enum_histogram_callback; |
108 } | 108 } |
109 | 109 |
110 void PerformanceTracker::RecordVideoFrameStats(const FrameStats& stats) { | 110 void PerformanceTracker::OnVideoFrameStats(const FrameStats& stats) { |
111 if (!is_paused_ && !upload_uma_stats_timer_.IsRunning()) { | 111 if (!is_paused_ && !upload_uma_stats_timer_.IsRunning()) { |
112 upload_uma_stats_timer_.Start( | 112 upload_uma_stats_timer_.Start( |
113 FROM_HERE, base::TimeDelta::FromSeconds(kStatsUpdatePeriodSeconds), | 113 FROM_HERE, base::TimeDelta::FromSeconds(kStatsUpdatePeriodSeconds), |
114 base::Bind(&PerformanceTracker::UploadRateStatsToUma, | 114 base::Bind(&PerformanceTracker::UploadRateStatsToUma, |
115 base::Unretained(this))); | 115 base::Unretained(this))); |
116 } | 116 } |
117 | 117 |
118 // Record this received packet, even if it is empty. | 118 // Record this received packet, even if it is empty. |
119 video_packet_rate_.Record(1); | 119 video_packet_rate_.Record(1); |
120 | 120 |
121 // Use only non-empty frames to estimate frame rate. | 121 // Use only non-empty frames to estimate frame rate. |
122 if (stats.frame_size) | 122 if (stats.host_stats.frame_size) |
123 video_frame_rate_.Record(1); | 123 video_frame_rate_.Record(1); |
124 | 124 |
125 video_bandwidth_.Record(stats.frame_size); | 125 video_bandwidth_.Record(stats.host_stats.frame_size); |
126 | 126 |
127 if (stats.capture_delay != base::TimeDelta::Max()) { | 127 if (stats.host_stats.capture_delay != base::TimeDelta::Max()) { |
128 video_capture_ms_.Record(stats.capture_delay.InMilliseconds()); | 128 video_capture_ms_.Record(stats.host_stats.capture_delay.InMilliseconds()); |
129 uma_custom_times_updater_.Run( | 129 uma_custom_times_updater_.Run( |
130 kVideoCaptureLatencyHistogram, stats.capture_delay.InMilliseconds(), | 130 kVideoCaptureLatencyHistogram, |
| 131 stats.host_stats.capture_delay.InMilliseconds(), |
131 kVideoActionsHistogramsMinMs, kVideoActionsHistogramsMaxMs, | 132 kVideoActionsHistogramsMinMs, kVideoActionsHistogramsMaxMs, |
132 kVideoActionsHistogramsBuckets); | 133 kVideoActionsHistogramsBuckets); |
133 } | 134 } |
134 | 135 |
135 if (stats.encode_delay != base::TimeDelta::Max()) { | 136 if (stats.host_stats.encode_delay != base::TimeDelta::Max()) { |
136 video_encode_ms_.Record(stats.encode_delay.InMilliseconds()); | 137 video_encode_ms_.Record(stats.host_stats.encode_delay.InMilliseconds()); |
137 uma_custom_times_updater_.Run( | 138 uma_custom_times_updater_.Run( |
138 kVideoEncodeLatencyHistogram, stats.encode_delay.InMilliseconds(), | 139 kVideoEncodeLatencyHistogram, |
| 140 stats.host_stats.encode_delay.InMilliseconds(), |
139 kVideoActionsHistogramsMinMs, kVideoActionsHistogramsMaxMs, | 141 kVideoActionsHistogramsMinMs, kVideoActionsHistogramsMaxMs, |
140 kVideoActionsHistogramsBuckets); | 142 kVideoActionsHistogramsBuckets); |
141 } | 143 } |
142 | 144 |
143 if (stats.capture_pending_delay != base::TimeDelta::Max()) { | 145 if (stats.host_stats.capture_pending_delay != base::TimeDelta::Max()) { |
144 uma_custom_times_updater_.Run(kCapturePendingLatencyHistogram, | |
145 stats.capture_pending_delay.InMilliseconds(), | |
146 kVideoActionsHistogramsMinMs, | |
147 kVideoActionsHistogramsMaxMs, | |
148 kVideoActionsHistogramsBuckets); | |
149 } | |
150 | |
151 if (stats.capture_overhead_delay != base::TimeDelta::Max()) { | |
152 uma_custom_times_updater_.Run(kCaptureOverheadHistogram, | |
153 stats.capture_overhead_delay.InMilliseconds(), | |
154 kVideoActionsHistogramsMinMs, | |
155 kVideoActionsHistogramsMaxMs, | |
156 kVideoActionsHistogramsBuckets); | |
157 } | |
158 | |
159 if (stats.encode_pending_delay != base::TimeDelta::Max()) { | |
160 uma_custom_times_updater_.Run(kEncodePendingLatencyHistogram, | |
161 stats.encode_pending_delay.InMilliseconds(), | |
162 kVideoActionsHistogramsMinMs, | |
163 kVideoActionsHistogramsMaxMs, | |
164 kVideoActionsHistogramsBuckets); | |
165 } | |
166 | |
167 if (stats.send_pending_delay != base::TimeDelta::Max()) { | |
168 uma_custom_times_updater_.Run( | 146 uma_custom_times_updater_.Run( |
169 kSendPendingLatencyHistogram, stats.send_pending_delay.InMilliseconds(), | 147 kCapturePendingLatencyHistogram, |
| 148 stats.host_stats.capture_pending_delay.InMilliseconds(), |
170 kVideoActionsHistogramsMinMs, kVideoActionsHistogramsMaxMs, | 149 kVideoActionsHistogramsMinMs, kVideoActionsHistogramsMaxMs, |
171 kVideoActionsHistogramsBuckets); | 150 kVideoActionsHistogramsBuckets); |
172 } | 151 } |
173 | 152 |
174 DCHECK(!stats.time_received.is_null()); | 153 if (stats.host_stats.capture_overhead_delay != base::TimeDelta::Max()) { |
| 154 uma_custom_times_updater_.Run( |
| 155 kCaptureOverheadHistogram, |
| 156 stats.host_stats.capture_overhead_delay.InMilliseconds(), |
| 157 kVideoActionsHistogramsMinMs, kVideoActionsHistogramsMaxMs, |
| 158 kVideoActionsHistogramsBuckets); |
| 159 } |
| 160 |
| 161 if (stats.host_stats.encode_pending_delay != base::TimeDelta::Max()) { |
| 162 uma_custom_times_updater_.Run( |
| 163 kEncodePendingLatencyHistogram, |
| 164 stats.host_stats.encode_pending_delay.InMilliseconds(), |
| 165 kVideoActionsHistogramsMinMs, kVideoActionsHistogramsMaxMs, |
| 166 kVideoActionsHistogramsBuckets); |
| 167 } |
| 168 |
| 169 if (stats.host_stats.send_pending_delay != base::TimeDelta::Max()) { |
| 170 uma_custom_times_updater_.Run( |
| 171 kSendPendingLatencyHistogram, |
| 172 stats.host_stats.send_pending_delay.InMilliseconds(), |
| 173 kVideoActionsHistogramsMinMs, kVideoActionsHistogramsMaxMs, |
| 174 kVideoActionsHistogramsBuckets); |
| 175 } |
| 176 |
| 177 DCHECK(!stats.client_stats.time_received.is_null()); |
175 | 178 |
176 // Report decode and render delay only for non-empty frames. | 179 // Report decode and render delay only for non-empty frames. |
177 if (stats.frame_size > 0) { | 180 if (stats.host_stats.frame_size > 0) { |
178 DCHECK(!stats.time_rendered.is_null()); | 181 DCHECK(!stats.client_stats.time_rendered.is_null()); |
179 DCHECK(!stats.time_decoded.is_null()); | 182 DCHECK(!stats.client_stats.time_decoded.is_null()); |
180 base::TimeDelta decode_delay = stats.time_decoded - stats.time_received; | 183 base::TimeDelta decode_delay = |
| 184 stats.client_stats.time_decoded - stats.client_stats.time_received; |
181 video_decode_ms_.Record(decode_delay.InMilliseconds()); | 185 video_decode_ms_.Record(decode_delay.InMilliseconds()); |
182 uma_custom_times_updater_.Run( | 186 uma_custom_times_updater_.Run( |
183 kVideoDecodeLatencyHistogram, decode_delay.InMilliseconds(), | 187 kVideoDecodeLatencyHistogram, decode_delay.InMilliseconds(), |
184 kVideoActionsHistogramsMinMs, kVideoActionsHistogramsMaxMs, | 188 kVideoActionsHistogramsMinMs, kVideoActionsHistogramsMaxMs, |
185 kVideoActionsHistogramsBuckets); | 189 kVideoActionsHistogramsBuckets); |
186 | 190 |
187 base::TimeDelta render_delay = stats.time_rendered - stats.time_decoded; | 191 base::TimeDelta render_delay = |
| 192 stats.client_stats.time_rendered - stats.client_stats.time_decoded; |
188 video_paint_ms_.Record(render_delay.InMilliseconds()); | 193 video_paint_ms_.Record(render_delay.InMilliseconds()); |
189 uma_custom_times_updater_.Run( | 194 uma_custom_times_updater_.Run( |
190 kVideoPaintLatencyHistogram, render_delay.InMilliseconds(), | 195 kVideoPaintLatencyHistogram, render_delay.InMilliseconds(), |
191 kVideoActionsHistogramsMinMs, kVideoActionsHistogramsMaxMs, | 196 kVideoActionsHistogramsMinMs, kVideoActionsHistogramsMaxMs, |
192 kVideoActionsHistogramsBuckets); | 197 kVideoActionsHistogramsBuckets); |
193 } | 198 } |
194 | 199 |
195 // |latest_event_timestamp| is set only for the first frame after an input | 200 // |latest_event_timestamp| is set only for the first frame after an input |
196 // event. | 201 // event. |
197 if (stats.latest_event_timestamp.is_null()) | 202 if (stats.host_stats.latest_event_timestamp.is_null()) |
198 return; | 203 return; |
199 | 204 |
200 // For empty frames use time_received as time_rendered. | 205 // For empty frames use time_received as time_rendered. |
201 base::TimeTicks time_rendered = | 206 base::TimeTicks time_rendered = (stats.host_stats.frame_size > 0) |
202 (stats.frame_size > 0) ? stats.time_rendered : stats.time_received; | 207 ? stats.client_stats.time_rendered |
| 208 : stats.client_stats.time_received; |
203 base::TimeDelta round_trip_latency = | 209 base::TimeDelta round_trip_latency = |
204 time_rendered - stats.latest_event_timestamp; | 210 time_rendered - stats.host_stats.latest_event_timestamp; |
205 round_trip_ms_.Record(round_trip_latency.InMilliseconds()); | 211 round_trip_ms_.Record(round_trip_latency.InMilliseconds()); |
206 uma_custom_times_updater_.Run( | 212 uma_custom_times_updater_.Run( |
207 kRoundTripLatencyHistogram, round_trip_latency.InMilliseconds(), | 213 kRoundTripLatencyHistogram, round_trip_latency.InMilliseconds(), |
208 kLatencyHistogramMinMs, kLatencyHistogramMaxMs, kLatencyHistogramBuckets); | 214 kLatencyHistogramMinMs, kLatencyHistogramMaxMs, kLatencyHistogramBuckets); |
209 | 215 |
210 // Report estimated network latency. | 216 // Report estimated network latency. |
211 if (stats.capture_delay != base::TimeDelta::Max() && | 217 if (stats.host_stats.capture_delay != base::TimeDelta::Max() && |
212 stats.encode_delay != base::TimeDelta::Max() && | 218 stats.host_stats.encode_delay != base::TimeDelta::Max() && |
213 stats.capture_pending_delay != base::TimeDelta::Max() && | 219 stats.host_stats.capture_pending_delay != base::TimeDelta::Max() && |
214 stats.capture_overhead_delay != base::TimeDelta::Max() && | 220 stats.host_stats.capture_overhead_delay != base::TimeDelta::Max() && |
215 stats.encode_pending_delay != base::TimeDelta::Max() && | 221 stats.host_stats.encode_pending_delay != base::TimeDelta::Max() && |
216 stats.send_pending_delay != base::TimeDelta::Max()) { | 222 stats.host_stats.send_pending_delay != base::TimeDelta::Max()) { |
217 // Calculate total processing time on host and client. | 223 // Calculate total processing time on host and client. |
218 base::TimeDelta total_processing_latency = | 224 base::TimeDelta total_processing_latency = |
219 stats.capture_delay + stats.encode_delay + stats.capture_pending_delay + | 225 stats.host_stats.capture_delay + stats.host_stats.encode_delay + |
220 stats.capture_overhead_delay + stats.encode_pending_delay + | 226 stats.host_stats.capture_pending_delay + |
221 stats.send_pending_delay + (time_rendered - stats.time_received); | 227 stats.host_stats.capture_overhead_delay + |
| 228 stats.host_stats.encode_pending_delay + |
| 229 stats.host_stats.send_pending_delay + |
| 230 (time_rendered - stats.client_stats.time_received); |
222 base::TimeDelta network_latency = | 231 base::TimeDelta network_latency = |
223 round_trip_latency - total_processing_latency; | 232 round_trip_latency - total_processing_latency; |
224 uma_custom_times_updater_.Run( | 233 uma_custom_times_updater_.Run( |
225 kNetworkLatencyHistogram, network_latency.InMilliseconds(), | 234 kNetworkLatencyHistogram, network_latency.InMilliseconds(), |
226 kVideoActionsHistogramsMinMs, kVideoActionsHistogramsMaxMs, | 235 kVideoActionsHistogramsMinMs, kVideoActionsHistogramsMaxMs, |
227 kVideoActionsHistogramsBuckets); | 236 kVideoActionsHistogramsBuckets); |
228 } | 237 } |
229 } | 238 } |
230 | 239 |
231 void PerformanceTracker::UploadRateStatsToUma() { | 240 void PerformanceTracker::UploadRateStatsToUma() { |
(...skipping 10 matching lines...) Expand all Loading... |
242 is_paused_ = paused; | 251 is_paused_ = paused; |
243 if (is_paused_) { | 252 if (is_paused_) { |
244 // Pause the UMA timer when the video is paused. It will be unpaused in | 253 // Pause the UMA timer when the video is paused. It will be unpaused in |
245 // RecordVideoFrameStats() when a new frame is received. | 254 // RecordVideoFrameStats() when a new frame is received. |
246 upload_uma_stats_timer_.Stop(); | 255 upload_uma_stats_timer_.Stop(); |
247 } | 256 } |
248 } | 257 } |
249 | 258 |
250 } // namespace protocol | 259 } // namespace protocol |
251 } // namespace remoting | 260 } // namespace remoting |
OLD | NEW |