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

Side by Side Diff: content/browser/media/capture/desktop_capture_device_aura.cc

Issue 615133002: Add support for a virtual display on ChromeOS (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix remaining comment periods (thanks achuithb@) Created 5 years, 10 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 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 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 "content/browser/media/capture/desktop_capture_device_aura.h" 5 #include "content/browser/media/capture/desktop_capture_device_aura.h"
6 6
7 #include "base/logging.h" 7 #include "base/logging.h"
8 #include "base/metrics/histogram.h" 8 #include "base/metrics/histogram.h"
9 #include "base/sys_info.h"
9 #include "base/timer/timer.h" 10 #include "base/timer/timer.h"
10 #include "cc/output/copy_output_request.h" 11 #include "cc/output/copy_output_request.h"
11 #include "cc/output/copy_output_result.h" 12 #include "cc/output/copy_output_result.h"
12 #include "content/browser/compositor/image_transport_factory.h" 13 #include "content/browser/compositor/image_transport_factory.h"
13 #include "content/browser/media/capture/content_video_capture_device_core.h" 14 #include "content/browser/media/capture/content_video_capture_device_core.h"
14 #include "content/browser/media/capture/desktop_capture_device_uma_types.h" 15 #include "content/browser/media/capture/desktop_capture_device_uma_types.h"
15 #include "content/common/gpu/client/gl_helper.h" 16 #include "content/common/gpu/client/gl_helper.h"
16 #include "content/public/browser/browser_thread.h" 17 #include "content/public/browser/browser_thread.h"
17 #include "content/public/browser/power_save_blocker.h" 18 #include "content/public/browser/power_save_blocker.h"
18 #include "media/base/video_util.h" 19 #include "media/base/video_util.h"
19 #include "media/video/capture/video_capture_types.h" 20 #include "media/video/capture/video_capture_types.h"
20 #include "skia/ext/image_operations.h" 21 #include "skia/ext/image_operations.h"
21 #include "third_party/skia/include/core/SkBitmap.h" 22 #include "third_party/skia/include/core/SkBitmap.h"
22 #include "ui/aura/client/screen_position_client.h" 23 #include "ui/aura/client/screen_position_client.h"
23 #include "ui/aura/env.h" 24 #include "ui/aura/env.h"
24 #include "ui/aura/window.h" 25 #include "ui/aura/window.h"
25 #include "ui/aura/window_observer.h" 26 #include "ui/aura/window_observer.h"
26 #include "ui/aura/window_tree_host.h" 27 #include "ui/aura/window_tree_host.h"
27 #include "ui/base/cursor/cursors_aura.h" 28 #include "ui/base/cursor/cursors_aura.h"
28 #include "ui/compositor/compositor.h" 29 #include "ui/compositor/compositor.h"
29 #include "ui/compositor/dip_util.h" 30 #include "ui/compositor/dip_util.h"
30 #include "ui/compositor/layer.h" 31 #include "ui/compositor/layer.h"
32 #include "ui/gfx/display.h"
33 #include "ui/gfx/display_observer.h"
31 #include "ui/gfx/screen.h" 34 #include "ui/gfx/screen.h"
32 35
36 #if defined(USE_ASH)
37 #include "ash/display/display_controller.h"
piman 2015/02/24 01:58:29 content/ is not allowed to depend on ash/
38 #include "ash/shell.h"
39 #include "ui/display/chromeos/display_configurator.h"
40 #endif
41
33 namespace content { 42 namespace content {
34 43
35 namespace { 44 namespace {
36 45
37 int clip_byte(int x) { 46 int clip_byte(int x) {
38 return std::max(0, std::min(x, 255)); 47 return std::max(0, std::min(x, 255));
39 } 48 }
40 49
41 int alpha_blend(int alpha, int src, int dst) { 50 int alpha_blend(int alpha, int src, int dst) {
42 return (src * alpha + dst * (255 - alpha)) / 255; 51 return (src * alpha + dst * (255 - alpha)) / 255;
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
86 } 95 }
87 } 96 }
88 } 97 }
89 cursor_bitmap.unlockPixels(); 98 cursor_bitmap.unlockPixels();
90 } 99 }
91 100
92 class DesktopVideoCaptureMachine 101 class DesktopVideoCaptureMachine
93 : public VideoCaptureMachine, 102 : public VideoCaptureMachine,
94 public aura::WindowObserver, 103 public aura::WindowObserver,
95 public ui::CompositorObserver, 104 public ui::CompositorObserver,
105 public gfx::DisplayObserver,
96 public base::SupportsWeakPtr<DesktopVideoCaptureMachine> { 106 public base::SupportsWeakPtr<DesktopVideoCaptureMachine> {
97 public: 107 public:
98 DesktopVideoCaptureMachine(const DesktopMediaID& source); 108 DesktopVideoCaptureMachine(const DesktopMediaID& source);
99 ~DesktopVideoCaptureMachine() override; 109 ~DesktopVideoCaptureMachine() override;
100 110
101 // VideoCaptureFrameSource overrides. 111 // VideoCaptureFrameSource overrides.
102 bool Start(const scoped_refptr<ThreadSafeCaptureOracle>& oracle_proxy, 112 bool Start(const scoped_refptr<ThreadSafeCaptureOracle>& oracle_proxy,
103 const media::VideoCaptureParams& params) override; 113 const media::VideoCaptureParams& params) override;
104 void Stop(const base::Closure& callback) override; 114 void Stop(const base::Closure& callback) override;
105 115
106 // Implements aura::WindowObserver. 116 // Implements aura::WindowObserver.
107 void OnWindowBoundsChanged(aura::Window* window, 117 void OnWindowBoundsChanged(aura::Window* window,
108 const gfx::Rect& old_bounds, 118 const gfx::Rect& old_bounds,
109 const gfx::Rect& new_bounds) override; 119 const gfx::Rect& new_bounds) override;
110 void OnWindowDestroyed(aura::Window* window) override; 120 void OnWindowDestroyed(aura::Window* window) override;
111 void OnWindowAddedToRootWindow(aura::Window* window) override; 121 void OnWindowAddedToRootWindow(aura::Window* window) override;
112 void OnWindowRemovingFromRootWindow(aura::Window* window, 122 void OnWindowRemovingFromRootWindow(aura::Window* window,
113 aura::Window* new_root) override; 123 aura::Window* new_root) override;
114 124
115 // Implements ui::CompositorObserver. 125 // Implements ui::CompositorObserver.
116 void OnCompositingDidCommit(ui::Compositor* compositor) override {} 126 void OnCompositingDidCommit(ui::Compositor* compositor) override {}
117 void OnCompositingStarted(ui::Compositor* compositor, 127 void OnCompositingStarted(ui::Compositor* compositor,
118 base::TimeTicks start_time) override {} 128 base::TimeTicks start_time) override {}
119 void OnCompositingEnded(ui::Compositor* compositor) override; 129 void OnCompositingEnded(ui::Compositor* compositor) override;
120 void OnCompositingAborted(ui::Compositor* compositor) override {} 130 void OnCompositingAborted(ui::Compositor* compositor) override {}
121 void OnCompositingLockStateChanged(ui::Compositor* compositor) override {} 131 void OnCompositingLockStateChanged(ui::Compositor* compositor) override {}
122 void OnCompositingShuttingDown(ui::Compositor* compositor) override {} 132 void OnCompositingShuttingDown(ui::Compositor* compositor) override {}
123 133
134 // Implements gfx::DisplayObserver.
135 void OnDisplayAdded(const gfx::Display& new_display) override;
136 void OnDisplayRemoved(const gfx::Display& old_display) override {}
137 void OnDisplayMetricsChanged(const gfx::Display& display,
138 uint32_t changed_metrics) override {}
139
124 private: 140 private:
125 // Captures a frame. 141 // Captures a frame.
126 // |dirty| is false for timer polls and true for compositor updates. 142 // |dirty| is false for timer polls and true for compositor updates.
127 void Capture(bool dirty); 143 void Capture(bool dirty);
128 144
129 // Update capture size. Must be called on the UI thread. 145 // Update capture size. Must be called on the UI thread.
130 void UpdateCaptureSize(); 146 void UpdateCaptureSize();
131 147
132 // Response callback for cc::Layer::RequestCopyOfOutput(). 148 // Response callback for cc::Layer::RequestCopyOfOutput().
133 void DidCopyOutput( 149 void DidCopyOutput(
(...skipping 11 matching lines...) Expand all
145 scoped_ptr<cc::CopyOutputResult> result); 161 scoped_ptr<cc::CopyOutputResult> result);
146 162
147 // Helper function to update cursor state. 163 // Helper function to update cursor state.
148 // |region_in_frame| defines the desktop bound in the captured frame. 164 // |region_in_frame| defines the desktop bound in the captured frame.
149 // Returns the current cursor position in captured frame. 165 // Returns the current cursor position in captured frame.
150 gfx::Point UpdateCursorState(const gfx::Rect& region_in_frame); 166 gfx::Point UpdateCursorState(const gfx::Rect& region_in_frame);
151 167
152 // Clears cursor state. 168 // Clears cursor state.
153 void ClearCursorState(); 169 void ClearCursorState();
154 170
171 // Start the capture after setup.
172 void StartCapture();
173
155 // The window associated with the desktop. 174 // The window associated with the desktop.
156 aura::Window* desktop_window_; 175 aura::Window* desktop_window_;
157 176
158 // The timer that kicks off period captures. 177 // The timer that kicks off period captures.
159 base::Timer timer_; 178 base::Timer timer_;
160 179
161 // The id of the window being captured. 180 // The id of the window being captured.
162 DesktopMediaID window_id_; 181 DesktopMediaID window_id_;
163 182
164 // Makes all the decisions about which frames to copy, and how. 183 // Makes all the decisions about which frames to copy, and how.
(...skipping 18 matching lines...) Expand all
183 }; 202 };
184 203
185 DesktopVideoCaptureMachine::DesktopVideoCaptureMachine( 204 DesktopVideoCaptureMachine::DesktopVideoCaptureMachine(
186 const DesktopMediaID& source) 205 const DesktopMediaID& source)
187 : desktop_window_(NULL), 206 : desktop_window_(NULL),
188 timer_(true, true), 207 timer_(true, true),
189 window_id_(source) {} 208 window_id_(source) {}
190 209
191 DesktopVideoCaptureMachine::~DesktopVideoCaptureMachine() {} 210 DesktopVideoCaptureMachine::~DesktopVideoCaptureMachine() {}
192 211
193 bool DesktopVideoCaptureMachine::Start( 212 void DesktopVideoCaptureMachine::StartCapture() {
194 const scoped_refptr<ThreadSafeCaptureOracle>& oracle_proxy,
195 const media::VideoCaptureParams& params) {
196 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
197
198 desktop_window_ = content::DesktopMediaID::GetAuraWindowById(window_id_);
199 if (!desktop_window_)
200 return false;
201
202 // If the associated layer is already destroyed then return failure.
203 ui::Layer* layer = desktop_window_->layer();
204 if (!layer)
205 return false;
206
207 DCHECK(oracle_proxy.get());
208 oracle_proxy_ = oracle_proxy;
209 capture_params_ = params;
210
211 // Update capture size. 213 // Update capture size.
212 UpdateCaptureSize(); 214 UpdateCaptureSize();
213 215
214 // Start observing window events. 216 // Start observing window events.
215 desktop_window_->AddObserver(this); 217 desktop_window_->AddObserver(this);
216 218
217 // Start observing compositor updates. 219 // Start observing compositor updates.
218 if (desktop_window_->GetHost()) 220 if (desktop_window_->GetHost())
219 desktop_window_->GetHost()->compositor()->AddObserver(this); 221 desktop_window_->GetHost()->compositor()->AddObserver(this);
220 222
221 power_save_blocker_.reset(PowerSaveBlocker::Create( 223 power_save_blocker_.reset(PowerSaveBlocker::Create(
222 PowerSaveBlocker::kPowerSaveBlockPreventDisplaySleep, 224 PowerSaveBlocker::kPowerSaveBlockPreventDisplaySleep,
223 "DesktopCaptureDevice is running").release()); 225 "DesktopCaptureDevice is running").release());
224 226
225 // Starts timer. 227 // Starts timer.
226 timer_.Start(FROM_HERE, oracle_proxy_->min_capture_period(), 228 timer_.Start(FROM_HERE, oracle_proxy_->min_capture_period(),
227 base::Bind(&DesktopVideoCaptureMachine::Capture, AsWeakPtr(), 229 base::Bind(&DesktopVideoCaptureMachine::Capture, AsWeakPtr(),
228 false)); 230 false));
231 }
232
233 bool DesktopVideoCaptureMachine::Start(
Sergey Ulanov 2015/02/23 23:16:12 Can the virtual-screen logic be moved out of this
oshima 2015/02/24 19:43:21 and please move ash code from content/.
robert.bradford 2015/03/03 19:58:00 I've started working on the non virtual display re
234 const scoped_refptr<ThreadSafeCaptureOracle>& oracle_proxy,
235 const media::VideoCaptureParams& params) {
236 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
237
238 capture_params_ = params;
239 DCHECK(oracle_proxy.get());
240 oracle_proxy_ = oracle_proxy;
241
242 #if defined(USE_ASH)
oshima 2015/02/24 19:43:21 no USE_ASH in content/. You probably should just u
243 // Window for virtual display is available asynchronously after request. The
244 // DisplayObserver on the screen will be notified of the new display and
245 // Window and start the capture.
246 if (window_id_.type == DesktopMediaID::TYPE_AURA_VIRTUAL_SCREEN) {
247 DCHECK(base::SysInfo::IsRunningOnChromeOS());
248 ui::DisplayConfigurator* configurator =
249 ash::Shell::GetInstance()->display_configurator();
250 gfx::Screen::GetNativeScreen()->AddObserver(this);
251 configurator->EnableVirtualDisplay(make_scoped_ptr(
252 new ui::DisplayMode(params.requested_format.frame_size, false, 60)));
253 return true;
254 }
255 #else
256 desktop_window_ = content::DesktopMediaID::GetAuraWindowById(window_id_);
257 #endif
258
259 if (!desktop_window_)
260 return false;
261
262 // If the associated layer is already destroyed then return failure.
263 ui::Layer* layer = desktop_window_->layer();
264 if (!layer)
265 return false;
266
267 StartCapture();
229 268
230 return true; 269 return true;
231 } 270 }
232 271
233 void DesktopVideoCaptureMachine::Stop(const base::Closure& callback) { 272 void DesktopVideoCaptureMachine::Stop(const base::Closure& callback) {
234 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 273 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
235 power_save_blocker_.reset(); 274 power_save_blocker_.reset();
236 275
237 // Stop observing compositor and window events. 276 // Stop observing compositor and window events.
238 if (desktop_window_) { 277 if (desktop_window_) {
239 aura::WindowTreeHost* window_host = desktop_window_->GetHost(); 278 aura::WindowTreeHost* window_host = desktop_window_->GetHost();
240 // In the host destructor the compositor is destroyed before the window. 279 // In the host destructor the compositor is destroyed before the window.
241 if (window_host && window_host->compositor()) 280 if (window_host && window_host->compositor())
242 window_host->compositor()->RemoveObserver(this); 281 window_host->compositor()->RemoveObserver(this);
243 desktop_window_->RemoveObserver(this); 282 desktop_window_->RemoveObserver(this);
244 desktop_window_ = NULL; 283 desktop_window_ = NULL;
245 } 284 }
246 285
286 #if defined(USE_ASH)
287 if (window_id_.type == DesktopMediaID::TYPE_AURA_VIRTUAL_SCREEN) {
288 gfx::Screen::GetNativeScreen()->RemoveObserver(this);
289 ash::Shell::GetInstance()->display_configurator()->DisableVirtualDisplay();
290 }
291 #endif
292
247 // Stop timer. 293 // Stop timer.
248 timer_.Stop(); 294 timer_.Stop();
249 295
250 callback.Run(); 296 callback.Run();
251 } 297 }
252 298
253 void DesktopVideoCaptureMachine::UpdateCaptureSize() { 299 void DesktopVideoCaptureMachine::UpdateCaptureSize() {
254 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 300 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
255 if (oracle_proxy_.get() && desktop_window_) { 301 if (oracle_proxy_.get() && desktop_window_) {
256 ui::Layer* layer = desktop_window_->layer(); 302 ui::Layer* layer = desktop_window_->layer();
(...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after
500 DCHECK(window == desktop_window_); 546 DCHECK(window == desktop_window_);
501 window->GetHost()->compositor()->RemoveObserver(this); 547 window->GetHost()->compositor()->RemoveObserver(this);
502 } 548 }
503 549
504 void DesktopVideoCaptureMachine::OnCompositingEnded( 550 void DesktopVideoCaptureMachine::OnCompositingEnded(
505 ui::Compositor* compositor) { 551 ui::Compositor* compositor) {
506 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind( 552 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind(
507 &DesktopVideoCaptureMachine::Capture, AsWeakPtr(), true)); 553 &DesktopVideoCaptureMachine::Capture, AsWeakPtr(), true));
508 } 554 }
509 555
556 void DesktopVideoCaptureMachine::OnDisplayAdded(
557 const gfx::Display& new_display) {
558 #if defined(USE_ASH)
559 DCHECK(base::SysInfo::IsRunningOnChromeOS());
560 ui::DisplayConfigurator* configurator =
561 ash::Shell::GetInstance()->display_configurator();
562 int64 display_id = configurator->GetVirtualDisplayId();
563
564 if (display_id == new_display.id()) {
565 desktop_window_ = ash::Shell::GetInstance()
566 ->display_controller()
567 ->GetRootWindowForDisplayId(display_id);
568
569 // We only need the observer for a short time.
570 gfx::Screen::GetNativeScreen()->RemoveObserver(this);
571
572 if (desktop_window_ && desktop_window_->layer()) {
573 StartCapture();
574 } else {
575 Stop(base::Bind(&base::DoNothing));
576 }
577 }
578 }
579 #endif
510 } // namespace 580 } // namespace
511 581
512 DesktopCaptureDeviceAura::DesktopCaptureDeviceAura( 582 DesktopCaptureDeviceAura::DesktopCaptureDeviceAura(
513 const DesktopMediaID& source) 583 const DesktopMediaID& source)
514 : core_(new ContentVideoCaptureDeviceCore(scoped_ptr<VideoCaptureMachine>( 584 : core_(new ContentVideoCaptureDeviceCore(scoped_ptr<VideoCaptureMachine>(
515 new DesktopVideoCaptureMachine(source)))) {} 585 new DesktopVideoCaptureMachine(source)))) {}
516 586
517 DesktopCaptureDeviceAura::~DesktopCaptureDeviceAura() { 587 DesktopCaptureDeviceAura::~DesktopCaptureDeviceAura() {
518 DVLOG(2) << "DesktopCaptureDeviceAura@" << this << " destroying."; 588 DVLOG(2) << "DesktopCaptureDeviceAura@" << this << " destroying.";
519 } 589 }
(...skipping 12 matching lines...) Expand all
532 scoped_ptr<Client> client) { 602 scoped_ptr<Client> client) {
533 DVLOG(1) << "Allocating " << params.requested_format.frame_size.ToString(); 603 DVLOG(1) << "Allocating " << params.requested_format.frame_size.ToString();
534 core_->AllocateAndStart(params, client.Pass()); 604 core_->AllocateAndStart(params, client.Pass());
535 } 605 }
536 606
537 void DesktopCaptureDeviceAura::StopAndDeAllocate() { 607 void DesktopCaptureDeviceAura::StopAndDeAllocate() {
538 core_->StopAndDeAllocate(); 608 core_->StopAndDeAllocate();
539 } 609 }
540 610
541 } // namespace content 611 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698