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

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

Issue 1864813002: Tab/Desktop Capture: Use requests instead of timer-based refreshing. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@video_refresh_from_sinks
Patch Set: Addressed comments from PS2, and sampling decision logic change w.r.t. recent animation. Created 4 years, 8 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"
11 #include "base/strings/stringprintf.h" 11 #include "base/strings/stringprintf.h"
12 12
13 namespace media { 13 namespace media {
14 14
15 namespace { 15 namespace {
16 16
17 // This value controls how many redundant, timer-base captures occur when the 17 // When a non-compositor event arrives after animation has halted, this
18 // content is static. Redundantly capturing the same frame allows iterative 18 // controls how much time must elapse before deciding to allow a capture.
19 // quality enhancement, and also allows the buffer to fill in "buffered mode". 19 const int kAnimationHaltPeriodBeforeOtherSamplingMicros = 250000;
20 // 20
21 // TODO(nick): Controlling this here is a hack and a layering violation, since 21 // When estimating frame durations, this is the hard upper-bound on the
22 // it's a strategy specific to the WebRTC consumer, and probably just papers 22 // estimate.
23 // over some frame dropping and quality bugs. It should either be controlled at 23 const int kUpperBoundDurationEstimateMicros = 1000000; // 1 second
24 // a higher level, or else redundant frame generation should be pushed down
25 // further into the WebRTC encoding stack.
26 const int kNumRedundantCapturesOfStaticContent = 200;
27 24
28 // The half-life of data points provided to the accumulator used when evaluating 25 // The half-life of data points provided to the accumulator used when evaluating
29 // the recent utilization of the buffer pool. This value is based on a 26 // the recent utilization of the buffer pool. This value is based on a
30 // simulation, and reacts quickly to change to avoid depleting the buffer pool 27 // simulation, and reacts quickly to change to avoid depleting the buffer pool
31 // (which would cause hard frame drops). 28 // (which would cause hard frame drops).
32 const int kBufferUtilizationEvaluationMicros = 200000; // 0.2 seconds 29 const int kBufferUtilizationEvaluationMicros = 200000; // 0.2 seconds
33 30
34 // The half-life of data points provided to the accumulator used when evaluating 31 // The half-life of data points provided to the accumulator used when evaluating
35 // the recent resource utilization of the consumer. The trade-off made here is 32 // the recent resource utilization of the consumer. The trade-off made here is
36 // reaction time versus over-reacting to outlier data points. 33 // reaction time versus over-reacting to outlier data points.
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
99 96
100 VideoCaptureOracle::VideoCaptureOracle( 97 VideoCaptureOracle::VideoCaptureOracle(
101 base::TimeDelta min_capture_period, 98 base::TimeDelta min_capture_period,
102 const gfx::Size& max_frame_size, 99 const gfx::Size& max_frame_size,
103 media::ResolutionChangePolicy resolution_change_policy, 100 media::ResolutionChangePolicy resolution_change_policy,
104 bool enable_auto_throttling) 101 bool enable_auto_throttling)
105 : auto_throttling_enabled_(enable_auto_throttling), 102 : auto_throttling_enabled_(enable_auto_throttling),
106 next_frame_number_(0), 103 next_frame_number_(0),
107 last_successfully_delivered_frame_number_(-1), 104 last_successfully_delivered_frame_number_(-1),
108 num_frames_pending_(0), 105 num_frames_pending_(0),
109 smoothing_sampler_(min_capture_period, 106 smoothing_sampler_(min_capture_period),
110 kNumRedundantCapturesOfStaticContent),
111 content_sampler_(min_capture_period), 107 content_sampler_(min_capture_period),
112 resolution_chooser_(max_frame_size, resolution_change_policy), 108 resolution_chooser_(max_frame_size, resolution_change_policy),
113 buffer_pool_utilization_(base::TimeDelta::FromMicroseconds( 109 buffer_pool_utilization_(base::TimeDelta::FromMicroseconds(
114 kBufferUtilizationEvaluationMicros)), 110 kBufferUtilizationEvaluationMicros)),
115 estimated_capable_area_(base::TimeDelta::FromMicroseconds( 111 estimated_capable_area_(base::TimeDelta::FromMicroseconds(
116 kConsumerCapabilityEvaluationMicros)) { 112 kConsumerCapabilityEvaluationMicros)) {
117 VLOG(1) << "Auto-throttling is " 113 VLOG(1) << "Auto-throttling is "
118 << (auto_throttling_enabled_ ? "enabled." : "disabled."); 114 << (auto_throttling_enabled_ ? "enabled." : "disabled.");
119 } 115 }
120 116
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
157 duration_of_next_frame_ = content_sampler_.sampling_period(); 153 duration_of_next_frame_ = content_sampler_.sampling_period();
158 } 154 }
159 last_time_animation_was_detected_ = event_time; 155 last_time_animation_was_detected_ = event_time;
160 } else { 156 } else {
161 VLOG_IF(1, had_proposal) << "Content sampler detects animation ended."; 157 VLOG_IF(1, had_proposal) << "Content sampler detects animation ended.";
162 should_sample = smoothing_sampler_.ShouldSample(); 158 should_sample = smoothing_sampler_.ShouldSample();
163 } 159 }
164 break; 160 break;
165 } 161 }
166 162
167 case kTimerPoll: 163 case kActiveRefreshRequest:
168 // While the timer is firing, only allow a sampling if there are none 164 case kPassiveRefreshRequest:
169 // currently in-progress. 165 case kMouseCursorUpdate:
170 if (num_frames_pending_ == 0) 166 // Only allow non-compositor samplings when content has not recently been
171 should_sample = smoothing_sampler_.IsOverdueForSamplingAt(event_time); 167 // animating, and only if there are no samplings currently in progress.
168 if (num_frames_pending_ == 0) {
169 if (!content_sampler_.HasProposal() ||
170 ((event_time - last_time_animation_was_detected_).InMicroseconds() >
171 kAnimationHaltPeriodBeforeOtherSamplingMicros)) {
172 smoothing_sampler_.ConsiderPresentationEvent(event_time);
173 should_sample = smoothing_sampler_.ShouldSample();
174 }
175 }
172 break; 176 break;
173 177
174 case kMouseCursorUpdate:
175 // Only allow a sampling if there are none currently in-progress.
176 if (num_frames_pending_ == 0) {
177 smoothing_sampler_.ConsiderPresentationEvent(event_time);
178 should_sample = smoothing_sampler_.ShouldSample();
179 }
180 break;
181 case kNumEvents: 178 case kNumEvents:
182 NOTREACHED(); 179 NOTREACHED();
183 break; 180 break;
184 } 181 }
185 182
186 if (!should_sample) 183 if (!should_sample)
187 return false; 184 return false;
188 185
189 // If the exact duration of the next frame has not been determined, estimate 186 // If the exact duration of the next frame has not been determined, estimate
190 // it using the difference between the current and last frame. 187 // it using the difference between the current and last frame.
191 if (duration_of_next_frame_.is_zero()) { 188 if (duration_of_next_frame_.is_zero()) {
192 if (next_frame_number_ > 0) { 189 if (next_frame_number_ > 0) {
193 duration_of_next_frame_ = 190 duration_of_next_frame_ =
194 event_time - GetFrameTimestamp(next_frame_number_ - 1); 191 event_time - GetFrameTimestamp(next_frame_number_ - 1);
195 } 192 }
196 const base::TimeDelta upper_bound = base::TimeDelta::FromMilliseconds( 193 const base::TimeDelta upper_bound =
197 SmoothEventSampler::OVERDUE_DIRTY_THRESHOLD_MILLIS); 194 base::TimeDelta::FromMilliseconds(kUpperBoundDurationEstimateMicros);
198 duration_of_next_frame_ = 195 duration_of_next_frame_ =
199 std::max(std::min(duration_of_next_frame_, upper_bound), 196 std::max(std::min(duration_of_next_frame_, upper_bound),
200 smoothing_sampler_.min_capture_period()); 197 smoothing_sampler_.min_capture_period());
201 } 198 }
202 199
203 // Update |capture_size_| and reset all feedback signal accumulators if 200 // Update |capture_size_| and reset all feedback signal accumulators if
204 // either: 1) this is the first frame; or 2) |resolution_chooser_| has an 201 // either: 1) this is the first frame; or 2) |resolution_chooser_| has an
205 // updated capture size and sufficient time has passed since the last size 202 // updated capture size and sufficient time has passed since the last size
206 // change. 203 // change.
207 if (next_frame_number_ == 0) { 204 if (next_frame_number_ == 0) {
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after
333 // Translate the utilization metric to be in terms of the capable frame area 330 // Translate the utilization metric to be in terms of the capable frame area
334 // and update the feedback accumulators. Research suggests utilization is at 331 // and update the feedback accumulators. Research suggests utilization is at
335 // most linearly proportional to area, and typically is sublinear. Either 332 // most linearly proportional to area, and typically is sublinear. Either
336 // way, the end-to-end system should converge to the right place using the 333 // way, the end-to-end system should converge to the right place using the
337 // more-conservative assumption (linear). 334 // more-conservative assumption (linear).
338 const int area_at_full_utilization = 335 const int area_at_full_utilization =
339 base::saturated_cast<int>(capture_size_.GetArea() / resource_utilization); 336 base::saturated_cast<int>(capture_size_.GetArea() / resource_utilization);
340 estimated_capable_area_.Update(area_at_full_utilization, timestamp); 337 estimated_capable_area_.Update(area_at_full_utilization, timestamp);
341 } 338 }
342 339
340 // static
341 const char* VideoCaptureOracle::EventAsString(Event event) {
342 switch (event) {
343 case kCompositorUpdate:
344 return "compositor";
345 case kActiveRefreshRequest:
346 return "active_refresh";
347 case kPassiveRefreshRequest:
348 return "passive_refresh";
349 case kMouseCursorUpdate:
350 return "mouse";
351 case kNumEvents:
352 break;
353 }
354 NOTREACHED();
355 return "unknown";
356 }
357
343 base::TimeTicks VideoCaptureOracle::GetFrameTimestamp(int frame_number) const { 358 base::TimeTicks VideoCaptureOracle::GetFrameTimestamp(int frame_number) const {
344 DCHECK(IsFrameInRecentHistory(frame_number)); 359 DCHECK(IsFrameInRecentHistory(frame_number));
345 return frame_timestamps_[frame_number % kMaxFrameTimestamps]; 360 return frame_timestamps_[frame_number % kMaxFrameTimestamps];
346 } 361 }
347 362
348 void VideoCaptureOracle::SetFrameTimestamp(int frame_number, 363 void VideoCaptureOracle::SetFrameTimestamp(int frame_number,
349 base::TimeTicks timestamp) { 364 base::TimeTicks timestamp) {
350 DCHECK(IsFrameInRecentHistory(frame_number)); 365 DCHECK(IsFrameInRecentHistory(frame_number));
351 frame_timestamps_[frame_number % kMaxFrameTimestamps] = timestamp; 366 frame_timestamps_[frame_number % kMaxFrameTimestamps] = timestamp;
352 } 367 }
(...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after
533 // Content is not animating, so permit an immediate increase in the capture 548 // Content is not animating, so permit an immediate increase in the capture
534 // area. This allows the system to quickly improve the quality of 549 // area. This allows the system to quickly improve the quality of
535 // non-animating content (frame drops are not much of a concern). 550 // non-animating content (frame drops are not much of a concern).
536 VLOG(2) << "Proposing a " 551 VLOG(2) << "Proposing a "
537 << (100.0 * (increased_area - current_area) / current_area) 552 << (100.0 * (increased_area - current_area) / current_area)
538 << "% increase in capture area for non-animating content. :-)"; 553 << "% increase in capture area for non-animating content. :-)";
539 return increased_area; 554 return increased_area;
540 } 555 }
541 556
542 } // namespace media 557 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698