Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2015 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 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 "media/capture/content/video_capture_oracle.h" | 5 #include "media/capture/content/video_capture_oracle.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 | 8 |
| 9 #include "base/format_macros.h" | 9 #include "base/format_macros.h" |
| 10 #include "base/numerics/safe_conversions.h" | 10 #include "base/numerics/safe_conversions.h" |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 94 | 94 |
| 95 } // anonymous namespace | 95 } // anonymous namespace |
| 96 | 96 |
| 97 VideoCaptureOracle::VideoCaptureOracle( | 97 VideoCaptureOracle::VideoCaptureOracle( |
| 98 base::TimeDelta min_capture_period, | 98 base::TimeDelta min_capture_period, |
| 99 const gfx::Size& max_frame_size, | 99 const gfx::Size& max_frame_size, |
| 100 media::ResolutionChangePolicy resolution_change_policy, | 100 media::ResolutionChangePolicy resolution_change_policy, |
| 101 bool enable_auto_throttling) | 101 bool enable_auto_throttling) |
| 102 : auto_throttling_enabled_(enable_auto_throttling), | 102 : auto_throttling_enabled_(enable_auto_throttling), |
| 103 next_frame_number_(0), | 103 next_frame_number_(0), |
| 104 source_is_dirty_(true), | |
| 105 last_event_causing_capture_(kPassiveRefreshRequest), | |
| 104 last_successfully_delivered_frame_number_(-1), | 106 last_successfully_delivered_frame_number_(-1), |
| 105 num_frames_pending_(0), | 107 num_frames_pending_(0), |
| 106 smoothing_sampler_(min_capture_period), | 108 smoothing_sampler_(min_capture_period), |
| 107 content_sampler_(min_capture_period), | 109 content_sampler_(min_capture_period), |
| 108 resolution_chooser_(max_frame_size, resolution_change_policy), | 110 resolution_chooser_(max_frame_size, resolution_change_policy), |
| 109 buffer_pool_utilization_(base::TimeDelta::FromMicroseconds( | 111 buffer_pool_utilization_(base::TimeDelta::FromMicroseconds( |
| 110 kBufferUtilizationEvaluationMicros)), | 112 kBufferUtilizationEvaluationMicros)), |
| 111 estimated_capable_area_(base::TimeDelta::FromMicroseconds( | 113 estimated_capable_area_(base::TimeDelta::FromMicroseconds( |
| 112 kConsumerCapabilityEvaluationMicros)) { | 114 kConsumerCapabilityEvaluationMicros)) { |
| 113 VLOG(1) << "Auto-throttling is " | 115 VLOG(1) << "Auto-throttling is " |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 131 base::TimeTicks event_time) { | 133 base::TimeTicks event_time) { |
| 132 DCHECK_GE(event, 0); | 134 DCHECK_GE(event, 0); |
| 133 DCHECK_LT(event, kNumEvents); | 135 DCHECK_LT(event, kNumEvents); |
| 134 if (event_time < last_event_time_[event]) { | 136 if (event_time < last_event_time_[event]) { |
| 135 LOG(WARNING) << "Event time is not monotonically non-decreasing. " | 137 LOG(WARNING) << "Event time is not monotonically non-decreasing. " |
| 136 << "Deciding not to capture this frame."; | 138 << "Deciding not to capture this frame."; |
| 137 return false; | 139 return false; |
| 138 } | 140 } |
| 139 last_event_time_[event] = event_time; | 141 last_event_time_[event] = event_time; |
| 140 | 142 |
| 143 // If the event indicates a change to the source content, set a flag that will | |
| 144 // prevent passive refresh requests until a capture is made. | |
| 145 if (event != kActiveRefreshRequest && event != kPassiveRefreshRequest) | |
| 146 source_is_dirty_ = true; | |
| 147 | |
| 141 bool should_sample = false; | 148 bool should_sample = false; |
| 142 duration_of_next_frame_ = base::TimeDelta(); | 149 duration_of_next_frame_ = base::TimeDelta(); |
| 143 switch (event) { | 150 switch (event) { |
| 144 case kCompositorUpdate: { | 151 case kCompositorUpdate: { |
| 145 smoothing_sampler_.ConsiderPresentationEvent(event_time); | 152 smoothing_sampler_.ConsiderPresentationEvent(event_time); |
| 146 const bool had_proposal = content_sampler_.HasProposal(); | 153 const bool had_proposal = content_sampler_.HasProposal(); |
| 147 content_sampler_.ConsiderPresentationEvent(damage_rect, event_time); | 154 content_sampler_.ConsiderPresentationEvent(damage_rect, event_time); |
| 148 if (content_sampler_.HasProposal()) { | 155 if (content_sampler_.HasProposal()) { |
| 149 VLOG_IF(1, !had_proposal) << "Content sampler now detects animation."; | 156 VLOG_IF(1, !had_proposal) << "Content sampler now detects animation."; |
| 150 should_sample = content_sampler_.ShouldSample(); | 157 should_sample = content_sampler_.ShouldSample(); |
| 151 if (should_sample) { | 158 if (should_sample) { |
| 152 event_time = content_sampler_.frame_timestamp(); | 159 event_time = content_sampler_.frame_timestamp(); |
| 153 duration_of_next_frame_ = content_sampler_.sampling_period(); | 160 duration_of_next_frame_ = content_sampler_.sampling_period(); |
| 154 } | 161 } |
| 155 last_time_animation_was_detected_ = event_time; | 162 last_time_animation_was_detected_ = event_time; |
| 156 } else { | 163 } else { |
| 157 VLOG_IF(1, had_proposal) << "Content sampler detects animation ended."; | 164 VLOG_IF(1, had_proposal) << "Content sampler detects animation ended."; |
| 158 should_sample = smoothing_sampler_.ShouldSample(); | 165 should_sample = smoothing_sampler_.ShouldSample(); |
| 159 } | 166 } |
| 160 break; | 167 break; |
| 161 } | 168 } |
| 162 | 169 |
| 170 case kPassiveRefreshRequest: | |
| 171 if (source_is_dirty_) | |
| 172 break; | |
| 173 // Intentional flow-through to next case here! | |
| 163 case kActiveRefreshRequest: | 174 case kActiveRefreshRequest: |
| 164 case kPassiveRefreshRequest: | |
| 165 case kMouseCursorUpdate: | 175 case kMouseCursorUpdate: |
| 166 // Only allow non-compositor samplings when content has not recently been | 176 // Only allow non-compositor samplings when content has not recently been |
| 167 // animating, and only if there are no samplings currently in progress. | 177 // animating, and only if there are no samplings currently in progress. |
| 168 if (num_frames_pending_ == 0) { | 178 if (num_frames_pending_ == 0) { |
| 169 if (!content_sampler_.HasProposal() || | 179 if (!content_sampler_.HasProposal() || |
| 170 ((event_time - last_time_animation_was_detected_).InMicroseconds() > | 180 ((event_time - last_time_animation_was_detected_).InMicroseconds() > |
| 171 kAnimationHaltPeriodBeforeOtherSamplingMicros)) { | 181 kAnimationHaltPeriodBeforeOtherSamplingMicros)) { |
| 172 smoothing_sampler_.ConsiderPresentationEvent(event_time); | 182 smoothing_sampler_.ConsiderPresentationEvent(event_time); |
| 173 should_sample = smoothing_sampler_.ShouldSample(); | 183 should_sample = smoothing_sampler_.ShouldSample(); |
| 174 } | 184 } |
| 175 } | 185 } |
| 176 break; | 186 break; |
| 177 | 187 |
| 178 case kNumEvents: | 188 case kNumEvents: |
| 179 NOTREACHED(); | 189 NOTREACHED(); |
| 180 break; | 190 break; |
| 181 } | 191 } |
| 182 | 192 |
| 183 if (!should_sample) | 193 if (!should_sample) |
| 184 return false; | 194 return false; |
| 195 last_event_causing_capture_ = event; | |
| 185 | 196 |
| 186 // If the exact duration of the next frame has not been determined, estimate | 197 // If the exact duration of the next frame has not been determined, estimate |
| 187 // it using the difference between the current and last frame. | 198 // it using the difference between the current and last frame. |
| 188 if (duration_of_next_frame_.is_zero()) { | 199 if (duration_of_next_frame_.is_zero()) { |
| 189 if (next_frame_number_ > 0) { | 200 if (next_frame_number_ > 0) { |
| 190 duration_of_next_frame_ = | 201 duration_of_next_frame_ = |
| 191 event_time - GetFrameTimestamp(next_frame_number_ - 1); | 202 event_time - GetFrameTimestamp(next_frame_number_ - 1); |
| 192 } | 203 } |
| 193 const base::TimeDelta upper_bound = | 204 const base::TimeDelta upper_bound = |
| 194 base::TimeDelta::FromMilliseconds(kUpperBoundDurationEstimateMicros); | 205 base::TimeDelta::FromMilliseconds(kUpperBoundDurationEstimateMicros); |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 214 return true; | 225 return true; |
| 215 } | 226 } |
| 216 | 227 |
| 217 int VideoCaptureOracle::next_frame_number() const { | 228 int VideoCaptureOracle::next_frame_number() const { |
| 218 return next_frame_number_; | 229 return next_frame_number_; |
| 219 } | 230 } |
| 220 | 231 |
| 221 void VideoCaptureOracle::RecordCapture(double pool_utilization) { | 232 void VideoCaptureOracle::RecordCapture(double pool_utilization) { |
| 222 DCHECK(std::isfinite(pool_utilization) && pool_utilization >= 0.0); | 233 DCHECK(std::isfinite(pool_utilization) && pool_utilization >= 0.0); |
| 223 | 234 |
| 235 if (last_event_causing_capture_ != kPassiveRefreshRequest) | |
|
miu
2017/03/24 21:17:28
Per discussion, this shouldn't be necessary. So, j
braveyao
2017/03/24 23:12:27
Done.
| |
| 236 source_is_dirty_ = false; | |
| 237 | |
| 224 smoothing_sampler_.RecordSample(); | 238 smoothing_sampler_.RecordSample(); |
| 225 const base::TimeTicks timestamp = GetFrameTimestamp(next_frame_number_); | 239 const base::TimeTicks timestamp = GetFrameTimestamp(next_frame_number_); |
| 226 content_sampler_.RecordSample(timestamp); | 240 content_sampler_.RecordSample(timestamp); |
| 227 | 241 |
| 228 if (auto_throttling_enabled_) { | 242 if (auto_throttling_enabled_) { |
| 229 buffer_pool_utilization_.Update(pool_utilization, timestamp); | 243 buffer_pool_utilization_.Update(pool_utilization, timestamp); |
| 230 AnalyzeAndAdjust(timestamp); | 244 AnalyzeAndAdjust(timestamp); |
| 231 } | 245 } |
| 232 | 246 |
| 233 num_frames_pending_++; | 247 num_frames_pending_++; |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 264 return false; | 278 return false; |
| 265 } | 279 } |
| 266 | 280 |
| 267 if (!IsFrameInRecentHistory(frame_number)) { | 281 if (!IsFrameInRecentHistory(frame_number)) { |
| 268 LOG(WARNING) << "Very old capture being ignored: frame #" << frame_number; | 282 LOG(WARNING) << "Very old capture being ignored: frame #" << frame_number; |
| 269 return false; | 283 return false; |
| 270 } | 284 } |
| 271 | 285 |
| 272 if (!capture_was_successful) { | 286 if (!capture_was_successful) { |
| 273 VLOG(2) << "Capture of frame #" << frame_number << " was not successful."; | 287 VLOG(2) << "Capture of frame #" << frame_number << " was not successful."; |
| 288 // Since capture of this frame might have been required for capturing an | |
| 289 // update to the source content, set the dirty flag. | |
| 290 source_is_dirty_ = true; | |
| 274 return false; | 291 return false; |
| 275 } | 292 } |
| 276 | 293 |
| 277 DCHECK_NE(last_successfully_delivered_frame_number_, frame_number); | 294 DCHECK_NE(last_successfully_delivered_frame_number_, frame_number); |
| 278 last_successfully_delivered_frame_number_ = frame_number; | 295 last_successfully_delivered_frame_number_ = frame_number; |
| 279 | 296 |
| 280 *frame_timestamp = GetFrameTimestamp(frame_number); | 297 *frame_timestamp = GetFrameTimestamp(frame_number); |
| 281 | 298 |
| 282 // If enabled, log a measurement of how this frame timestamp has incremented | 299 // If enabled, log a measurement of how this frame timestamp has incremented |
| 283 // in relation to an ideal increment. | 300 // in relation to an ideal increment. |
| (...skipping 268 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 552 // Content is not animating, so permit an immediate increase in the capture | 569 // Content is not animating, so permit an immediate increase in the capture |
| 553 // area. This allows the system to quickly improve the quality of | 570 // area. This allows the system to quickly improve the quality of |
| 554 // non-animating content (frame drops are not much of a concern). | 571 // non-animating content (frame drops are not much of a concern). |
| 555 VLOG(2) << "Proposing a " | 572 VLOG(2) << "Proposing a " |
| 556 << (100.0 * (increased_area - current_area) / current_area) | 573 << (100.0 * (increased_area - current_area) / current_area) |
| 557 << "% increase in capture area for non-animating content. :-)"; | 574 << "% increase in capture area for non-animating content. :-)"; |
| 558 return increased_area; | 575 return increased_area; |
| 559 } | 576 } |
| 560 | 577 |
| 561 } // namespace media | 578 } // namespace media |
| OLD | NEW |