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

Side by Side Diff: content/browser/renderer_host/media/web_contents_video_capture_device.cc

Issue 13956003: Tab capture: do 200 rendundant captures of static content. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Self-review fixes. Created 7 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 // Implementation notes: This needs to work on a variety of hardware 5 // Implementation notes: This needs to work on a variety of hardware
6 // configurations where the speed of the CPU and GPU greatly affect overall 6 // configurations where the speed of the CPU and GPU greatly affect overall
7 // performance. Spanning several threads, the process of capturing has been 7 // performance. Spanning several threads, the process of capturing has been
8 // split up into four conceptual stages: 8 // split up into four conceptual stages:
9 // 9 //
10 // 1. Reserve Buffer: Before a frame can be captured, a slot in the consumer's 10 // 1. Reserve Buffer: Before a frame can be captured, a slot in the consumer's
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
96 96
97 namespace content { 97 namespace content {
98 98
99 namespace { 99 namespace {
100 100
101 const int kMinFrameWidth = 2; 101 const int kMinFrameWidth = 2;
102 const int kMinFrameHeight = 2; 102 const int kMinFrameHeight = 2;
103 const int kMaxFramesInFlight = 2; 103 const int kMaxFramesInFlight = 2;
104 const int kMaxSnapshotsInFlight = 1; 104 const int kMaxSnapshotsInFlight = 1;
105 105
106 // This value controls how many redundant, timer-base captures occur when the
107 // content is static. Redundantly capturing the same frame allows iterative
108 // quality enhancement, and also allows the buffer to fill in "buffered mode".
109 //
110 // TODO(nick): Controlling this here is a hack and a layering violation, since
111 // it's a strategy specific to the WebRTC consumer, and probably just papers
112 // over some frame dropping and quality bugs. It should either be controlled at
113 // a higher level, or else redundant frame generation should be pushed down
114 // further into the WebRTC encoding stack.
115 const int kNumRedundantCapturesOfStaticContent = 200;
116
106 // TODO(nick): Remove this once frame subscription is supported on Aura and 117 // TODO(nick): Remove this once frame subscription is supported on Aura and
107 // Linux. 118 // Linux.
108 #if (defined(OS_WIN) || defined(OS_MACOSX)) && !defined(USE_AURA) 119 #if (defined(OS_WIN) || defined(OS_MACOSX)) && !defined(USE_AURA)
109 const bool kAcceleratedSubscriberIsSupported = true; 120 const bool kAcceleratedSubscriberIsSupported = true;
110 #else 121 #else
111 const bool kAcceleratedSubscriberIsSupported = false; 122 const bool kAcceleratedSubscriberIsSupported = false;
112 #endif 123 #endif
113 124
114 typedef base::Callback<void(base::Time, bool)> DeliverFrameCallback; 125 typedef base::Callback<void(base::Time, bool)> DeliverFrameCallback;
115 126
(...skipping 296 matching lines...) Expand 10 before | Expand all | Expand 10 after
412 423
413 DISALLOW_COPY_AND_ASSIGN(VideoFrameDeliveryLog); 424 DISALLOW_COPY_AND_ASSIGN(VideoFrameDeliveryLog);
414 }; 425 };
415 426
416 CaptureOracle::CaptureOracle(media::VideoCaptureDevice::EventHandler* consumer, 427 CaptureOracle::CaptureOracle(media::VideoCaptureDevice::EventHandler* consumer,
417 base::TimeDelta capture_period) 428 base::TimeDelta capture_period)
418 : capture_period_(capture_period), 429 : capture_period_(capture_period),
419 consumer_(consumer), 430 consumer_(consumer),
420 frame_number_(0), 431 frame_number_(0),
421 is_started_(false), 432 is_started_(false),
422 sampler_(capture_period_, kAcceleratedSubscriberIsSupported) {} 433 sampler_(capture_period_, kAcceleratedSubscriberIsSupported,
434 kNumRedundantCapturesOfStaticContent) {}
423 435
424 bool CaptureOracle::ObserveEventAndDecideCapture( 436 bool CaptureOracle::ObserveEventAndDecideCapture(
425 Event event, 437 Event event,
426 scoped_refptr<media::VideoFrame>* storage, 438 scoped_refptr<media::VideoFrame>* storage,
427 RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback* callback) { 439 RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback* callback) {
428 base::AutoLock guard(lock_); 440 base::AutoLock guard(lock_);
429 441
430 if (!consumer_ || !is_started_) 442 if (!consumer_ || !is_started_)
431 return false; // Capture is stopped. 443 return false; // Capture is stopped.
432 444
(...skipping 813 matching lines...) Expand 10 before | Expand all | Expand 10 after
1246 void WebContentsVideoCaptureDevice::DeAllocate() { 1258 void WebContentsVideoCaptureDevice::DeAllocate() {
1247 impl_->DeAllocate(); 1259 impl_->DeAllocate();
1248 } 1260 }
1249 1261
1250 const media::VideoCaptureDevice::Name& 1262 const media::VideoCaptureDevice::Name&
1251 WebContentsVideoCaptureDevice::device_name() { 1263 WebContentsVideoCaptureDevice::device_name() {
1252 return device_name_; 1264 return device_name_;
1253 } 1265 }
1254 1266
1255 SmoothEventSampler::SmoothEventSampler(base::TimeDelta capture_period, 1267 SmoothEventSampler::SmoothEventSampler(base::TimeDelta capture_period,
1256 bool events_are_reliable) 1268 bool events_are_reliable,
1269 int redundant_capture_goal)
1257 : events_are_reliable_(events_are_reliable), 1270 : events_are_reliable_(events_are_reliable),
1258 capture_period_(capture_period) {} 1271 capture_period_(capture_period),
1272 redundant_capture_goal_(redundant_capture_goal),
1273 last_sample_count_(0) {}
1259 1274
1260 bool SmoothEventSampler::AddEventAndConsiderSampling(base::Time now) { 1275 bool SmoothEventSampler::AddEventAndConsiderSampling(base::Time now) {
1261 current_event_ = now; 1276 current_event_ = now;
1262 1277
1263 // If we've never sampled, then the choice is obvious. 1278 // If we've never sampled, then the choice is obvious.
1264 if (last_sample_.is_null()) 1279 if (last_sample_count_ == 0)
1265 return true; 1280 return true;
1266 1281
1267 // TODO(nick): Actually track the effective frame rate here, and use an 1282 // TODO(nick): Actually track the effective frame rate here, and use an
1268 // uncertainty window based on that (half seems like a reasonable choice). E.g 1283 // uncertainty window based on that (half seems like a reasonable choice). E.g
1269 // if content is updating every 16.6ms, and we're hoping to sampling every 1284 // if content is updating every 16.6ms, and we're hoping to sampling every
1270 // 100ms, then we might consider sampling events no sooner than (100ms - 1285 // 100ms, then we might consider sampling events no sooner than (100ms -
1271 // 8.3ms) from the last sample. 1286 // 8.3ms) from the last sample.
1272 base::TimeDelta uncertainty_window = capture_period_ / 10; 1287 base::TimeDelta uncertainty_window = capture_period_ / 10;
1273 1288
1274 base::TimeDelta interval = current_event_ - last_sample_; 1289 base::TimeDelta interval = current_event_ - last_sample_;
1275 return interval >= (capture_period_ - uncertainty_window); 1290 return interval >= (capture_period_ - uncertainty_window);
1276 } 1291 }
1277 1292
1278 void SmoothEventSampler::RecordSample() { 1293 void SmoothEventSampler::RecordSample() {
1279 if (!current_event_.is_null()) 1294 if (!current_event_.is_null()) {
1295 last_sample_count_ = 0;
1280 last_sample_ = current_event_; 1296 last_sample_ = current_event_;
1297 }
1298 last_sample_count_++;
1281 current_event_ = base::Time(); 1299 current_event_ = base::Time();
1282 } 1300 }
1283 1301
1284 bool SmoothEventSampler::IsOverdueForSamplingAt(base::Time now) const { 1302 bool SmoothEventSampler::IsOverdueForSamplingAt(base::Time now) const {
1285 if (last_sample_.is_null()) 1303 if (last_sample_count_ == 0)
1286 return true; // Definitely old and dirty. 1304 return true; // Definitely old and dirty.
1287 1305
1288 // If we don't get events on compositor updates on this platform, then we 1306 // If we don't get events on compositor updates on this platform, then we
1289 // don't reliably know whether we're dirty. 1307 // don't reliably know whether we're dirty.
1290 if (events_are_reliable_) { 1308 if (events_are_reliable_) {
1291 if (current_event_.is_null()) 1309 if (current_event_.is_null() &&
1310 last_sample_count_ >= redundant_capture_goal_) {
1292 return false; // Not dirty. 1311 return false; // Not dirty.
1312 }
1293 } 1313 }
1294 1314
1295 // If we're dirty but not yet old, then we've recently gotten updates, so we 1315 // If we're dirty but not yet old, then we've recently gotten updates, so we
1296 // won't request a sample just yet. 1316 // won't request a sample just yet.
1297 base::TimeDelta dirty_interval = now - last_sample_; 1317 base::TimeDelta dirty_interval = now - last_sample_;
1298 if (dirty_interval < capture_period_ * 2) 1318 if (dirty_interval < capture_period_ * 2)
1299 return false; 1319 return false;
1300 else 1320 else
1301 return true; 1321 return true;
1302 } 1322 }
1303 1323
1304 base::Time SmoothEventSampler::GetLastSampledEvent() { 1324 base::Time SmoothEventSampler::GetLastSampledEvent() {
1305 return last_sample_; 1325 return last_sample_;
1306 } 1326 }
1307 1327
1308 } // namespace content 1328 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698