Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1030)

Side by Side Diff: media/capture/content/video_capture_oracle.cc

Issue 2770923003: TabCapture: enforce active refresh if there is un-sampled compositor update (Closed)
Patch Set: Apply suggested patch Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698