| 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 |