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

Side by Side Diff: media/video/capture/screen/screen_capturer_win.cc

Issue 12047101: Move screen capturers from remoting/capturer to media/video/capturer/screen (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 11 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 #include "remoting/capturer/video_frame_capturer.h" 5 #include "media/video/capture/screen/screen_capturer.h"
6 6
7 #include <windows.h> 7 #include <windows.h>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/bind_helpers.h" 10 #include "base/bind_helpers.h"
11 #include "base/file_path.h" 11 #include "base/file_path.h"
12 #include "base/logging.h" 12 #include "base/logging.h"
13 #include "base/memory/scoped_ptr.h" 13 #include "base/memory/scoped_ptr.h"
14 #include "base/scoped_native_library.h" 14 #include "base/scoped_native_library.h"
15 #include "base/stl_util.h" 15 #include "base/stl_util.h"
16 #include "base/time.h" 16 #include "base/time.h"
17 #include "base/utf_string_conversions.h" 17 #include "base/utf_string_conversions.h"
18 #include "base/win/scoped_gdi_object.h" 18 #include "base/win/scoped_gdi_object.h"
19 #include "base/win/scoped_hdc.h" 19 #include "base/win/scoped_hdc.h"
20 #include "remoting/capturer/capture_data.h" 20 #include "media/video/capture/screen/differ.h"
21 #include "remoting/capturer/differ.h" 21 #include "media/video/capture/screen/mouse_cursor_shape.h"
22 #include "remoting/capturer/mouse_cursor_shape.h" 22 #include "media/video/capture/screen/screen_capture_data.h"
23 #include "remoting/capturer/shared_buffer_factory.h" 23 #include "media/video/capture/screen/screen_capture_frame.h"
24 #include "remoting/capturer/video_frame.h" 24 #include "media/video/capture/screen/screen_capture_frame_queue.h"
25 #include "remoting/capturer/video_frame_capturer_helper.h" 25 #include "media/video/capture/screen/screen_capturer_helper.h"
26 #include "remoting/capturer/video_frame_queue.h" 26 #include "media/video/capture/screen/shared_buffer_factory.h"
27 #include "remoting/capturer/win/desktop.h" 27 #include "media/video/capture/screen/win/desktop.h"
28 #include "remoting/capturer/win/scoped_thread_desktop.h" 28 #include "media/video/capture/screen/win/scoped_thread_desktop.h"
29 #include "third_party/skia/include/core/SkColorPriv.h" 29 #include "third_party/skia/include/core/SkColorPriv.h"
30 30
31 namespace remoting { 31 namespace media {
32 32
33 namespace { 33 namespace {
34 34
35 // Constants from dwmapi.h. 35 // Constants from dwmapi.h.
36 const UINT DWM_EC_DISABLECOMPOSITION = 0; 36 const UINT DWM_EC_DISABLECOMPOSITION = 0;
37 const UINT DWM_EC_ENABLECOMPOSITION = 1; 37 const UINT DWM_EC_ENABLECOMPOSITION = 1;
38 38
39 typedef HRESULT (WINAPI * DwmEnableCompositionFunc)(UINT); 39 typedef HRESULT (WINAPI * DwmEnableCompositionFunc)(UINT);
40 40
41 const char kDwmapiLibraryName[] = "dwmapi"; 41 const char kDwmapiLibraryName[] = "dwmapi";
42 42
43 // Pixel colors used when generating cursor outlines. 43 // Pixel colors used when generating cursor outlines.
44 const uint32 kPixelBgraBlack = 0xff000000; 44 const uint32 kPixelBgraBlack = 0xff000000;
45 const uint32 kPixelBgraWhite = 0xffffffff; 45 const uint32 kPixelBgraWhite = 0xffffffff;
46 const uint32 kPixelBgraTransparent = 0x00000000; 46 const uint32 kPixelBgraTransparent = 0x00000000;
47 47
48 // A class representing a full-frame pixel buffer. 48 // A class representing a full-frame pixel buffer.
49 class VideoFrameWin : public VideoFrame { 49 class ScreenCaptureFrameWin : public ScreenCaptureFrame {
50 public: 50 public:
51 VideoFrameWin(HDC desktop_dc, const SkISize& size, 51 ScreenCaptureFrameWin(HDC desktop_dc, const SkISize& size,
52 SharedBufferFactory* shared_buffer_factory); 52 SharedBufferFactory* shared_buffer_factory);
53 virtual ~VideoFrameWin(); 53 virtual ~ScreenCaptureFrameWin();
54 54
55 // Returns handle of the device independent bitmap representing this frame 55 // Returns handle of the device independent bitmap representing this frame
56 // buffer to GDI. 56 // buffer to GDI.
57 HBITMAP GetBitmap(); 57 HBITMAP GetBitmap();
58 58
59 private: 59 private:
60 // Allocates a device independent bitmap representing this frame buffer to 60 // Allocates a device independent bitmap representing this frame buffer to
61 // GDI. 61 // GDI.
62 void AllocateBitmap(HDC desktop_dc, const SkISize& size); 62 void AllocateBitmap(HDC desktop_dc, const SkISize& size);
63 63
64 // Handle of the device independent bitmap representing this frame buffer to 64 // Handle of the device independent bitmap representing this frame buffer to
65 // GDI. 65 // GDI.
66 base::win::ScopedBitmap bitmap_; 66 base::win::ScopedBitmap bitmap_;
67 67
68 // Used to allocate shared memory buffers if set. 68 // Used to allocate shared memory buffers if set.
69 SharedBufferFactory* shared_buffer_factory_; 69 SharedBufferFactory* shared_buffer_factory_;
70 70
71 DISALLOW_COPY_AND_ASSIGN(VideoFrameWin); 71 DISALLOW_COPY_AND_ASSIGN(ScreenCaptureFrameWin);
72 }; 72 };
73 73
74 // VideoFrameCapturerWin captures 32bit RGB using GDI. 74 // ScreenCapturerWin captures 32bit RGB using GDI.
75 // 75 //
76 // VideoFrameCapturerWin is double-buffered as required by VideoFrameCapturer. 76 // ScreenCapturerWin is double-buffered as required by ScreenCapturer.
77 // See remoting/host/video_frame_capturer.h. 77 // See remoting/host/screen_capturer.h.
78 class VideoFrameCapturerWin : public VideoFrameCapturer { 78 class ScreenCapturerWin : public ScreenCapturer {
79 public: 79 public:
80 VideoFrameCapturerWin(); 80 ScreenCapturerWin();
81 explicit VideoFrameCapturerWin(SharedBufferFactory* shared_buffer_factory); 81 explicit ScreenCapturerWin(SharedBufferFactory* shared_buffer_factory);
82 virtual ~VideoFrameCapturerWin(); 82 virtual ~ScreenCapturerWin();
83 83
84 // Overridden from VideoFrameCapturer: 84 // Overridden from ScreenCapturer:
85 virtual void Start(Delegate* delegate) OVERRIDE; 85 virtual void Start(Delegate* delegate) OVERRIDE;
86 virtual void Stop() OVERRIDE; 86 virtual void Stop() OVERRIDE;
87 virtual void InvalidateRegion(const SkRegion& invalid_region) OVERRIDE; 87 virtual void InvalidateRegion(const SkRegion& invalid_region) OVERRIDE;
88 virtual void CaptureFrame() OVERRIDE; 88 virtual void CaptureFrame() OVERRIDE;
89 89
90 private: 90 private:
91 // Make sure that the device contexts match the screen configuration. 91 // Make sure that the device contexts match the screen configuration.
92 void PrepareCaptureResources(); 92 void PrepareCaptureResources();
93 93
94 // Creates a CaptureData instance wrapping the current framebuffer and 94 // Creates a ScreenCaptureData instance wrapping the current framebuffer and
95 // notifies |delegate_|. 95 // notifies |delegate_|.
96 void CaptureRegion(const SkRegion& region, 96 void CaptureRegion(const SkRegion& region,
97 const base::Time& capture_start_time); 97 const base::Time& capture_start_time);
98 98
99 // Captures the current screen contents into the current buffer. 99 // Captures the current screen contents into the current buffer.
100 void CaptureImage(); 100 void CaptureImage();
101 101
102 // Expand the cursor shape to add a white outline for visibility against 102 // Expand the cursor shape to add a white outline for visibility against
103 // dark backgrounds. 103 // dark backgrounds.
104 void AddCursorOutline(int width, int height, uint32* dst); 104 void AddCursorOutline(int width, int height, uint32* dst);
105 105
106 // Capture the current cursor shape. 106 // Capture the current cursor shape.
107 void CaptureCursor(); 107 void CaptureCursor();
108 108
109 // Used to allocate shared memory buffers if set. 109 // Used to allocate shared memory buffers if set.
110 SharedBufferFactory* shared_buffer_factory_; 110 SharedBufferFactory* shared_buffer_factory_;
111 111
112 Delegate* delegate_; 112 Delegate* delegate_;
113 113
114 // A thread-safe list of invalid rectangles, and the size of the most 114 // A thread-safe list of invalid rectangles, and the size of the most
115 // recently captured screen. 115 // recently captured screen.
116 VideoFrameCapturerHelper helper_; 116 ScreenCapturerHelper helper_;
117 117
118 // Snapshot of the last cursor bitmap we sent to the client. This is used 118 // Snapshot of the last cursor bitmap we sent to the client. This is used
119 // to diff against the current cursor so we only send a cursor-change 119 // to diff against the current cursor so we only send a cursor-change
120 // message when the shape has changed. 120 // message when the shape has changed.
121 MouseCursorShape last_cursor_; 121 MouseCursorShape last_cursor_;
122 122
123 ScopedThreadDesktop desktop_; 123 ScopedThreadDesktop desktop_;
124 124
125 // GDI resources used for screen capture. 125 // GDI resources used for screen capture.
126 scoped_ptr<base::win::ScopedGetDC> desktop_dc_; 126 scoped_ptr<base::win::ScopedGetDC> desktop_dc_;
127 base::win::ScopedCreateDC memory_dc_; 127 base::win::ScopedCreateDC memory_dc_;
128 128
129 // Queue of the frames buffers. 129 // Queue of the frames buffers.
130 VideoFrameQueue queue_; 130 ScreenCaptureFrameQueue queue_;
131 131
132 // Rectangle describing the bounds of the desktop device context. 132 // Rectangle describing the bounds of the desktop device context.
133 SkIRect desktop_dc_rect_; 133 SkIRect desktop_dc_rect_;
134 134
135 // Class to calculate the difference between two screen bitmaps. 135 // Class to calculate the difference between two screen bitmaps.
136 scoped_ptr<Differ> differ_; 136 scoped_ptr<Differ> differ_;
137 137
138 base::ScopedNativeLibrary dwmapi_library_; 138 base::ScopedNativeLibrary dwmapi_library_;
139 DwmEnableCompositionFunc composition_func_; 139 DwmEnableCompositionFunc composition_func_;
140 140
141 DISALLOW_COPY_AND_ASSIGN(VideoFrameCapturerWin); 141 DISALLOW_COPY_AND_ASSIGN(ScreenCapturerWin);
142 }; 142 };
143 143
144 // 3780 pixels per meter is equivalent to 96 DPI, typical on desktop monitors. 144 // 3780 pixels per meter is equivalent to 96 DPI, typical on desktop monitors.
145 static const int kPixelsPerMeter = 3780; 145 static const int kPixelsPerMeter = 3780;
146 146
147 VideoFrameWin::VideoFrameWin( 147 ScreenCaptureFrameWin::ScreenCaptureFrameWin(
148 HDC desktop_dc, 148 HDC desktop_dc,
149 const SkISize& size, 149 const SkISize& size,
150 SharedBufferFactory* shared_buffer_factory) 150 SharedBufferFactory* shared_buffer_factory)
151 : shared_buffer_factory_(shared_buffer_factory) { 151 : shared_buffer_factory_(shared_buffer_factory) {
152 // Allocate a shared memory buffer. 152 // Allocate a shared memory buffer.
153 uint32 buffer_size = 153 uint32 buffer_size =
154 size.width() * size.height() * CaptureData::kBytesPerPixel; 154 size.width() * size.height() * ScreenCaptureData::kBytesPerPixel;
155 if (shared_buffer_factory_) { 155 if (shared_buffer_factory_) {
156 scoped_refptr<SharedBuffer> shared_buffer = 156 scoped_refptr<SharedBuffer> shared_buffer =
157 shared_buffer_factory_->CreateSharedBuffer(buffer_size); 157 shared_buffer_factory_->CreateSharedBuffer(buffer_size);
158 CHECK(shared_buffer->ptr() != NULL); 158 CHECK(shared_buffer->ptr() != NULL);
159 set_shared_buffer(shared_buffer); 159 set_shared_buffer(shared_buffer);
160 } 160 }
161 161
162 AllocateBitmap(desktop_dc, size); 162 AllocateBitmap(desktop_dc, size);
163 } 163 }
164 164
165 VideoFrameWin::~VideoFrameWin() { 165 ScreenCaptureFrameWin::~ScreenCaptureFrameWin() {
166 if (shared_buffer()) 166 if (shared_buffer())
167 shared_buffer_factory_->ReleaseSharedBuffer(shared_buffer()); 167 shared_buffer_factory_->ReleaseSharedBuffer(shared_buffer());
168 } 168 }
169 169
170 HBITMAP VideoFrameWin::GetBitmap() { 170 HBITMAP ScreenCaptureFrameWin::GetBitmap() {
171 return bitmap_; 171 return bitmap_;
172 } 172 }
173 173
174 void VideoFrameWin::AllocateBitmap(HDC desktop_dc, const SkISize& size) { 174 void ScreenCaptureFrameWin::AllocateBitmap(HDC desktop_dc,
175 int bytes_per_row = size.width() * CaptureData::kBytesPerPixel; 175 const SkISize& size) {
176 int bytes_per_row = size.width() * ScreenCaptureData::kBytesPerPixel;
176 177
177 // Describe a device independent bitmap (DIB) that is the size of the desktop. 178 // Describe a device independent bitmap (DIB) that is the size of the desktop.
178 BITMAPINFO bmi; 179 BITMAPINFO bmi;
179 memset(&bmi, 0, sizeof(bmi)); 180 memset(&bmi, 0, sizeof(bmi));
180 bmi.bmiHeader.biHeight = -size.height(); 181 bmi.bmiHeader.biHeight = -size.height();
181 bmi.bmiHeader.biWidth = size.width(); 182 bmi.bmiHeader.biWidth = size.width();
182 bmi.bmiHeader.biPlanes = 1; 183 bmi.bmiHeader.biPlanes = 1;
183 bmi.bmiHeader.biBitCount = CaptureData::kBytesPerPixel * 8; 184 bmi.bmiHeader.biBitCount = ScreenCaptureData::kBytesPerPixel * 8;
184 bmi.bmiHeader.biSize = sizeof(bmi.bmiHeader); 185 bmi.bmiHeader.biSize = sizeof(bmi.bmiHeader);
185 bmi.bmiHeader.biSizeImage = bytes_per_row * size.height(); 186 bmi.bmiHeader.biSizeImage = bytes_per_row * size.height();
186 bmi.bmiHeader.biXPelsPerMeter = kPixelsPerMeter; 187 bmi.bmiHeader.biXPelsPerMeter = kPixelsPerMeter;
187 bmi.bmiHeader.biYPelsPerMeter = kPixelsPerMeter; 188 bmi.bmiHeader.biYPelsPerMeter = kPixelsPerMeter;
188 189
189 // Create the DIB, and store a pointer to its pixel buffer. 190 // Create the DIB, and store a pointer to its pixel buffer.
190 HANDLE section_handle = NULL; 191 HANDLE section_handle = NULL;
191 if (shared_buffer()) 192 if (shared_buffer())
192 section_handle = shared_buffer()->handle(); 193 section_handle = shared_buffer()->handle();
193 void* data = NULL; 194 void* data = NULL;
194 bitmap_ = CreateDIBSection(desktop_dc, &bmi, DIB_RGB_COLORS, &data, 195 bitmap_ = CreateDIBSection(desktop_dc, &bmi, DIB_RGB_COLORS, &data,
195 section_handle, 0); 196 section_handle, 0);
196 197
197 // TODO(wez): Cope gracefully with failure (crbug.com/157170). 198 // TODO(wez): Cope gracefully with failure (crbug.com/157170).
198 CHECK(bitmap_ != NULL); 199 CHECK(bitmap_ != NULL);
199 CHECK(data != NULL); 200 CHECK(data != NULL);
200 201
201 set_pixels(reinterpret_cast<uint8*>(data)); 202 set_pixels(reinterpret_cast<uint8*>(data));
202 set_dimensions(SkISize::Make(bmi.bmiHeader.biWidth, 203 set_dimensions(SkISize::Make(bmi.bmiHeader.biWidth,
203 std::abs(bmi.bmiHeader.biHeight))); 204 std::abs(bmi.bmiHeader.biHeight)));
204 set_bytes_per_row( 205 set_bytes_per_row(
205 bmi.bmiHeader.biSizeImage / std::abs(bmi.bmiHeader.biHeight)); 206 bmi.bmiHeader.biSizeImage / std::abs(bmi.bmiHeader.biHeight));
206 } 207 }
207 208
208 VideoFrameCapturerWin::VideoFrameCapturerWin() 209 ScreenCapturerWin::ScreenCapturerWin()
209 : shared_buffer_factory_(NULL), 210 : shared_buffer_factory_(NULL),
210 delegate_(NULL), 211 delegate_(NULL),
211 desktop_dc_rect_(SkIRect::MakeEmpty()), 212 desktop_dc_rect_(SkIRect::MakeEmpty()),
212 composition_func_(NULL) { 213 composition_func_(NULL) {
213 } 214 }
214 215
215 VideoFrameCapturerWin::VideoFrameCapturerWin( 216 ScreenCapturerWin::ScreenCapturerWin(
216 SharedBufferFactory* shared_buffer_factory) 217 SharedBufferFactory* shared_buffer_factory)
217 : shared_buffer_factory_(shared_buffer_factory), 218 : shared_buffer_factory_(shared_buffer_factory),
218 delegate_(NULL), 219 delegate_(NULL),
219 desktop_dc_rect_(SkIRect::MakeEmpty()), 220 desktop_dc_rect_(SkIRect::MakeEmpty()),
220 composition_func_(NULL) { 221 composition_func_(NULL) {
221 } 222 }
222 223
223 VideoFrameCapturerWin::~VideoFrameCapturerWin() { 224 ScreenCapturerWin::~ScreenCapturerWin() {
224 } 225 }
225 226
226 void VideoFrameCapturerWin::InvalidateRegion(const SkRegion& invalid_region) { 227 void ScreenCapturerWin::InvalidateRegion(const SkRegion& invalid_region) {
227 helper_.InvalidateRegion(invalid_region); 228 helper_.InvalidateRegion(invalid_region);
228 } 229 }
229 230
230 void VideoFrameCapturerWin::CaptureFrame() { 231 void ScreenCapturerWin::CaptureFrame() {
231 base::Time capture_start_time = base::Time::Now(); 232 base::Time capture_start_time = base::Time::Now();
232 233
233 // Force the system to power-up display hardware, if it has been suspended. 234 // Force the system to power-up display hardware, if it has been suspended.
234 SetThreadExecutionState(ES_DISPLAY_REQUIRED); 235 SetThreadExecutionState(ES_DISPLAY_REQUIRED);
235 236
236 // Make sure the GDI capture resources are up-to-date. 237 // Make sure the GDI capture resources are up-to-date.
237 PrepareCaptureResources(); 238 PrepareCaptureResources();
238 239
239 // Copy screen bits to the current buffer. 240 // Copy screen bits to the current buffer.
240 CaptureImage(); 241 CaptureImage();
241 242
242 const VideoFrame* current_buffer = queue_.current_frame(); 243 const ScreenCaptureFrame* current_buffer = queue_.current_frame();
243 const VideoFrame* last_buffer = queue_.previous_frame(); 244 const ScreenCaptureFrame* last_buffer = queue_.previous_frame();
244 if (last_buffer) { 245 if (last_buffer) {
245 // Make sure the differencer is set up correctly for these previous and 246 // Make sure the differencer is set up correctly for these previous and
246 // current screens. 247 // current screens.
247 if (!differ_.get() || 248 if (!differ_.get() ||
248 (differ_->width() != current_buffer->dimensions().width()) || 249 (differ_->width() != current_buffer->dimensions().width()) ||
249 (differ_->height() != current_buffer->dimensions().height()) || 250 (differ_->height() != current_buffer->dimensions().height()) ||
250 (differ_->bytes_per_row() != current_buffer->bytes_per_row())) { 251 (differ_->bytes_per_row() != current_buffer->bytes_per_row())) {
251 differ_.reset(new Differ(current_buffer->dimensions().width(), 252 differ_.reset(new Differ(current_buffer->dimensions().width(),
252 current_buffer->dimensions().height(), 253 current_buffer->dimensions().height(),
253 CaptureData::kBytesPerPixel, 254 ScreenCaptureData::kBytesPerPixel,
254 current_buffer->bytes_per_row())); 255 current_buffer->bytes_per_row()));
255 } 256 }
256 257
257 // Calculate difference between the two last captured frames. 258 // Calculate difference between the two last captured frames.
258 SkRegion region; 259 SkRegion region;
259 differ_->CalcDirtyRegion(last_buffer->pixels(), current_buffer->pixels(), 260 differ_->CalcDirtyRegion(last_buffer->pixels(), current_buffer->pixels(),
260 &region); 261 &region);
261 InvalidateRegion(region); 262 InvalidateRegion(region);
262 } else { 263 } else {
263 // No previous frame is available. Invalidate the whole screen. 264 // No previous frame is available. Invalidate the whole screen.
264 helper_.InvalidateScreen(current_buffer->dimensions()); 265 helper_.InvalidateScreen(current_buffer->dimensions());
265 } 266 }
266 267
267 // Wrap the captured frame into CaptureData structure and invoke 268 // Wrap the captured frame into ScreenCaptureData structure and invoke
268 // the completion callback. 269 // the completion callback.
269 SkRegion invalid_region; 270 SkRegion invalid_region;
270 helper_.SwapInvalidRegion(&invalid_region); 271 helper_.SwapInvalidRegion(&invalid_region);
271 CaptureRegion(invalid_region, capture_start_time); 272 CaptureRegion(invalid_region, capture_start_time);
272 273
273 // Check for cursor shape update. 274 // Check for cursor shape update.
274 CaptureCursor(); 275 CaptureCursor();
275 } 276 }
276 277
277 void VideoFrameCapturerWin::Start(Delegate* delegate) { 278 void ScreenCapturerWin::Start(Delegate* delegate) {
278 DCHECK(delegate_ == NULL); 279 DCHECK(delegate_ == NULL);
279 280
280 delegate_ = delegate; 281 delegate_ = delegate;
281 282
282 // Load dwmapi.dll dynamically since it is not available on XP. 283 // Load dwmapi.dll dynamically since it is not available on XP.
283 if (!dwmapi_library_.is_valid()) { 284 if (!dwmapi_library_.is_valid()) {
284 FilePath path(base::GetNativeLibraryName(UTF8ToUTF16(kDwmapiLibraryName))); 285 FilePath path(base::GetNativeLibraryName(UTF8ToUTF16(kDwmapiLibraryName)));
285 dwmapi_library_.Reset(base::LoadNativeLibrary(path, NULL)); 286 dwmapi_library_.Reset(base::LoadNativeLibrary(path, NULL));
286 } 287 }
287 288
288 if (dwmapi_library_.is_valid() && composition_func_ == NULL) { 289 if (dwmapi_library_.is_valid() && composition_func_ == NULL) {
289 composition_func_ = static_cast<DwmEnableCompositionFunc>( 290 composition_func_ = static_cast<DwmEnableCompositionFunc>(
290 dwmapi_library_.GetFunctionPointer("DwmEnableComposition")); 291 dwmapi_library_.GetFunctionPointer("DwmEnableComposition"));
291 } 292 }
292 293
293 // Vote to disable Aero composited desktop effects while capturing. Windows 294 // Vote to disable Aero composited desktop effects while capturing. Windows
294 // will restore Aero automatically if the process exits. This has no effect 295 // will restore Aero automatically if the process exits. This has no effect
295 // under Windows 8 or higher. See crbug.com/124018. 296 // under Windows 8 or higher. See crbug.com/124018.
296 if (composition_func_ != NULL) { 297 if (composition_func_ != NULL) {
297 (*composition_func_)(DWM_EC_DISABLECOMPOSITION); 298 (*composition_func_)(DWM_EC_DISABLECOMPOSITION);
298 } 299 }
299 } 300 }
300 301
301 void VideoFrameCapturerWin::Stop() { 302 void ScreenCapturerWin::Stop() {
302 // Restore Aero. 303 // Restore Aero.
303 if (composition_func_ != NULL) { 304 if (composition_func_ != NULL) {
304 (*composition_func_)(DWM_EC_ENABLECOMPOSITION); 305 (*composition_func_)(DWM_EC_ENABLECOMPOSITION);
305 } 306 }
306 307
307 delegate_ = NULL; 308 delegate_ = NULL;
308 } 309 }
309 310
310 void VideoFrameCapturerWin::PrepareCaptureResources() { 311 void ScreenCapturerWin::PrepareCaptureResources() {
311 // Switch to the desktop receiving user input if different from the current 312 // Switch to the desktop receiving user input if different from the current
312 // one. 313 // one.
313 scoped_ptr<Desktop> input_desktop = Desktop::GetInputDesktop(); 314 scoped_ptr<Desktop> input_desktop = Desktop::GetInputDesktop();
314 if (input_desktop.get() != NULL && !desktop_.IsSame(*input_desktop)) { 315 if (input_desktop.get() != NULL && !desktop_.IsSame(*input_desktop)) {
315 // Release GDI resources otherwise SetThreadDesktop will fail. 316 // Release GDI resources otherwise SetThreadDesktop will fail.
316 desktop_dc_.reset(); 317 desktop_dc_.reset();
317 memory_dc_.Set(NULL); 318 memory_dc_.Set(NULL);
318 319
319 // If SetThreadDesktop() fails, the thread is still assigned a desktop. 320 // If SetThreadDesktop() fails, the thread is still assigned a desktop.
320 // So we can continue capture screen bits, just from the wrong desktop. 321 // So we can continue capture screen bits, just from the wrong desktop.
(...skipping 21 matching lines...) Expand all
342 memory_dc_.Set(CreateCompatibleDC(*desktop_dc_)); 343 memory_dc_.Set(CreateCompatibleDC(*desktop_dc_));
343 desktop_dc_rect_ = screen_rect; 344 desktop_dc_rect_ = screen_rect;
344 345
345 // Make sure the frame buffers will be reallocated. 346 // Make sure the frame buffers will be reallocated.
346 queue_.SetAllFramesNeedUpdate(); 347 queue_.SetAllFramesNeedUpdate();
347 348
348 helper_.ClearInvalidRegion(); 349 helper_.ClearInvalidRegion();
349 } 350 }
350 } 351 }
351 352
352 void VideoFrameCapturerWin::CaptureRegion( 353 void ScreenCapturerWin::CaptureRegion(
353 const SkRegion& region, 354 const SkRegion& region,
354 const base::Time& capture_start_time) { 355 const base::Time& capture_start_time) {
355 const VideoFrame* current_buffer = queue_.current_frame(); 356 const ScreenCaptureFrame* current_buffer = queue_.current_frame();
356 357
357 scoped_refptr<CaptureData> data( 358 scoped_refptr<ScreenCaptureData> data(new ScreenCaptureData(
358 new CaptureData(current_buffer->pixels(), current_buffer->bytes_per_row(), 359 current_buffer->pixels(), current_buffer->bytes_per_row(),
359 current_buffer->dimensions())); 360 current_buffer->dimensions()));
360 data->mutable_dirty_region() = region; 361 data->mutable_dirty_region() = region;
361 data->set_shared_buffer(current_buffer->shared_buffer()); 362 data->set_shared_buffer(current_buffer->shared_buffer());
362 363
363 helper_.set_size_most_recent(data->size()); 364 helper_.set_size_most_recent(data->size());
364 365
365 queue_.DoneWithCurrentFrame(); 366 queue_.DoneWithCurrentFrame();
366 367
367 data->set_capture_time_ms( 368 data->set_capture_time_ms(
368 (base::Time::Now() - capture_start_time).InMillisecondsRoundedUp()); 369 (base::Time::Now() - capture_start_time).InMillisecondsRoundedUp());
369 delegate_->OnCaptureCompleted(data); 370 delegate_->OnCaptureCompleted(data);
370 } 371 }
371 372
372 void VideoFrameCapturerWin::CaptureImage() { 373 void ScreenCapturerWin::CaptureImage() {
373 // If the current buffer is from an older generation then allocate a new one. 374 // If the current buffer is from an older generation then allocate a new one.
374 // Note that we can't reallocate other buffers at this point, since the caller 375 // Note that we can't reallocate other buffers at this point, since the caller
375 // may still be reading from them. 376 // may still be reading from them.
376 if (queue_.current_frame_needs_update()) { 377 if (queue_.current_frame_needs_update()) {
377 DCHECK(desktop_dc_.get() != NULL); 378 DCHECK(desktop_dc_.get() != NULL);
378 DCHECK(memory_dc_.Get() != NULL); 379 DCHECK(memory_dc_.Get() != NULL);
379 380
380 SkISize size = SkISize::Make(desktop_dc_rect_.width(), 381 SkISize size = SkISize::Make(desktop_dc_rect_.width(),
381 desktop_dc_rect_.height()); 382 desktop_dc_rect_.height());
382 scoped_ptr<VideoFrameWin> buffer( 383 scoped_ptr<ScreenCaptureFrameWin> buffer(
383 new VideoFrameWin(*desktop_dc_, size, shared_buffer_factory_)); 384 new ScreenCaptureFrameWin(*desktop_dc_, size, shared_buffer_factory_));
384 queue_.ReplaceCurrentFrame(buffer.PassAs<VideoFrame>()); 385 queue_.ReplaceCurrentFrame(buffer.PassAs<ScreenCaptureFrame>());
385 } 386 }
386 387
387 // Select the target bitmap into the memory dc and copy the rect from desktop 388 // Select the target bitmap into the memory dc and copy the rect from desktop
388 // to memory. 389 // to memory.
389 VideoFrameWin* current = static_cast<VideoFrameWin*>(queue_.current_frame()); 390 ScreenCaptureFrameWin* current = static_cast<ScreenCaptureFrameWin*>(
391 queue_.current_frame());
390 HGDIOBJ previous_object = SelectObject(memory_dc_, current->GetBitmap()); 392 HGDIOBJ previous_object = SelectObject(memory_dc_, current->GetBitmap());
391 if (previous_object != NULL) { 393 if (previous_object != NULL) {
392 BitBlt(memory_dc_, 394 BitBlt(memory_dc_,
393 0, 0, desktop_dc_rect_.width(), desktop_dc_rect_.height(), 395 0, 0, desktop_dc_rect_.width(), desktop_dc_rect_.height(),
394 *desktop_dc_, 396 *desktop_dc_,
395 desktop_dc_rect_.x(), desktop_dc_rect_.y(), 397 desktop_dc_rect_.x(), desktop_dc_rect_.y(),
396 SRCCOPY | CAPTUREBLT); 398 SRCCOPY | CAPTUREBLT);
397 399
398 // Select back the previously selected object to that the device contect 400 // Select back the previously selected object to that the device contect
399 // could be destroyed independently of the bitmap if needed. 401 // could be destroyed independently of the bitmap if needed.
400 SelectObject(memory_dc_, previous_object); 402 SelectObject(memory_dc_, previous_object);
401 } 403 }
402 } 404 }
403 405
404 void VideoFrameCapturerWin::AddCursorOutline(int width, 406 void ScreenCapturerWin::AddCursorOutline(int width,
405 int height, 407 int height,
406 uint32* dst) { 408 uint32* dst) {
407 for (int y = 0; y < height; y++) { 409 for (int y = 0; y < height; y++) {
408 for (int x = 0; x < width; x++) { 410 for (int x = 0; x < width; x++) {
409 // If this is a transparent pixel (bgr == 0 and alpha = 0), check the 411 // If this is a transparent pixel (bgr == 0 and alpha = 0), check the
410 // neighbor pixels to see if this should be changed to an outline pixel. 412 // neighbor pixels to see if this should be changed to an outline pixel.
411 if (*dst == kPixelBgraTransparent) { 413 if (*dst == kPixelBgraTransparent) {
412 // Change to white pixel if any neighbors (top, bottom, left, right) 414 // Change to white pixel if any neighbors (top, bottom, left, right)
413 // are black. 415 // are black.
414 if ((y > 0 && dst[-width] == kPixelBgraBlack) || 416 if ((y > 0 && dst[-width] == kPixelBgraBlack) ||
415 (y < height - 1 && dst[width] == kPixelBgraBlack) || 417 (y < height - 1 && dst[width] == kPixelBgraBlack) ||
416 (x > 0 && dst[-1] == kPixelBgraBlack) || 418 (x > 0 && dst[-1] == kPixelBgraBlack) ||
417 (x < width - 1 && dst[1] == kPixelBgraBlack)) { 419 (x < width - 1 && dst[1] == kPixelBgraBlack)) {
418 *dst = kPixelBgraWhite; 420 *dst = kPixelBgraWhite;
419 } 421 }
420 } 422 }
421 dst++; 423 dst++;
422 } 424 }
423 } 425 }
424 } 426 }
425 427
426 void VideoFrameCapturerWin::CaptureCursor() { 428 void ScreenCapturerWin::CaptureCursor() {
427 CURSORINFO cursor_info; 429 CURSORINFO cursor_info;
428 cursor_info.cbSize = sizeof(CURSORINFO); 430 cursor_info.cbSize = sizeof(CURSORINFO);
429 if (!GetCursorInfo(&cursor_info)) { 431 if (!GetCursorInfo(&cursor_info)) {
430 VLOG(3) << "Unable to get cursor info. Error = " << GetLastError(); 432 VLOG(3) << "Unable to get cursor info. Error = " << GetLastError();
431 return; 433 return;
432 } 434 }
433 435
434 // Note that this does not need to be freed. 436 // Note that this does not need to be freed.
435 HCURSOR hcursor = cursor_info.hCursor; 437 HCURSOR hcursor = cursor_info.hCursor;
436 ICONINFO iinfo; 438 ICONINFO iinfo;
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
471 } 473 }
472 474
473 int width = bitmap.bmWidth; 475 int width = bitmap.bmWidth;
474 int height = bitmap.bmHeight; 476 int height = bitmap.bmHeight;
475 // For non-color cursors, the mask contains both an AND and an XOR mask and 477 // For non-color cursors, the mask contains both an AND and an XOR mask and
476 // the height includes both. Thus, the width is correct, but we need to 478 // the height includes both. Thus, the width is correct, but we need to
477 // divide by 2 to get the correct mask height. 479 // divide by 2 to get the correct mask height.
478 if (!color_bitmap) { 480 if (!color_bitmap) {
479 height /= 2; 481 height /= 2;
480 } 482 }
481 int data_size = height * width * CaptureData::kBytesPerPixel; 483 int data_size = height * width * ScreenCaptureData::kBytesPerPixel;
482 484
483 scoped_ptr<MouseCursorShape> cursor(new MouseCursorShape()); 485 scoped_ptr<MouseCursorShape> cursor(new MouseCursorShape());
484 cursor->data.resize(data_size); 486 cursor->data.resize(data_size);
485 uint8* cursor_dst_data = 487 uint8* cursor_dst_data =
486 reinterpret_cast<uint8*>(string_as_array(&cursor->data)); 488 reinterpret_cast<uint8*>(string_as_array(&cursor->data));
487 489
488 // Copy/convert cursor bitmap into format needed by chromotocol. 490 // Copy/convert cursor bitmap into format needed by chromotocol.
489 int row_bytes = bitmap.bmWidthBytes; 491 int row_bytes = bitmap.bmWidthBytes;
490 if (color_bitmap) { 492 if (color_bitmap) {
491 if (bitmap.bmPlanes != 1 || bitmap.bmBitsPixel != 32) { 493 if (bitmap.bmPlanes != 1 || bitmap.bmBitsPixel != 32) {
492 VLOG(3) << "Unsupported color cursor format. Error = " << GetLastError(); 494 VLOG(3) << "Unsupported color cursor format. Error = " << GetLastError();
493 return; 495 return;
494 } 496 }
495 497
496 // Copy across colour cursor imagery. 498 // Copy across colour cursor imagery.
497 // MouseCursorShape stores imagery top-down, and premultiplied 499 // MouseCursorShape stores imagery top-down, and premultiplied
498 // by the alpha channel, whereas windows stores them bottom-up 500 // by the alpha channel, whereas windows stores them bottom-up
499 // and not premultiplied. 501 // and not premultiplied.
500 uint8* cursor_src_data = reinterpret_cast<uint8*>(bitmap.bmBits); 502 uint8* cursor_src_data = reinterpret_cast<uint8*>(bitmap.bmBits);
501 uint8* src = cursor_src_data + ((height - 1) * row_bytes); 503 uint8* src = cursor_src_data + ((height - 1) * row_bytes);
502 uint8* dst = cursor_dst_data; 504 uint8* dst = cursor_dst_data;
503 for (int row = 0; row < height; ++row) { 505 for (int row = 0; row < height; ++row) {
504 for (int column = 0; column < width; ++column) { 506 for (int column = 0; column < width; ++column) {
505 dst[0] = SkAlphaMul(src[0], src[3]); 507 dst[0] = SkAlphaMul(src[0], src[3]);
506 dst[1] = SkAlphaMul(src[1], src[3]); 508 dst[1] = SkAlphaMul(src[1], src[3]);
507 dst[2] = SkAlphaMul(src[2], src[3]); 509 dst[2] = SkAlphaMul(src[2], src[3]);
508 dst[3] = src[3]; 510 dst[3] = src[3];
509 dst += CaptureData::kBytesPerPixel; 511 dst += ScreenCaptureData::kBytesPerPixel;
510 src += CaptureData::kBytesPerPixel; 512 src += ScreenCaptureData::kBytesPerPixel;
511 } 513 }
512 src -= row_bytes + (width * CaptureData::kBytesPerPixel); 514 src -= row_bytes + (width * ScreenCaptureData::kBytesPerPixel);
513 } 515 }
514 } else { 516 } else {
515 if (bitmap.bmPlanes != 1 || bitmap.bmBitsPixel != 1) { 517 if (bitmap.bmPlanes != 1 || bitmap.bmBitsPixel != 1) {
516 VLOG(3) << "Unsupported cursor mask format. Error = " << GetLastError(); 518 VLOG(3) << "Unsupported cursor mask format. Error = " << GetLastError();
517 return; 519 return;
518 } 520 }
519 521
520 // x2 because there are 2 masks in the bitmap: AND and XOR. 522 // x2 because there are 2 masks in the bitmap: AND and XOR.
521 int mask_bytes = height * row_bytes * 2; 523 int mask_bytes = height * row_bytes * 2;
522 scoped_array<uint8> mask(new uint8[mask_bytes]); 524 scoped_array<uint8> mask(new uint8[mask_bytes]);
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
576 578
577 // Record the last cursor image that we sent to the client. 579 // Record the last cursor image that we sent to the client.
578 last_cursor_ = *cursor; 580 last_cursor_ = *cursor;
579 581
580 delegate_->OnCursorShapeChanged(cursor.Pass()); 582 delegate_->OnCursorShapeChanged(cursor.Pass());
581 } 583 }
582 584
583 } // namespace 585 } // namespace
584 586
585 // static 587 // static
586 scoped_ptr<VideoFrameCapturer> VideoFrameCapturer::Create() { 588 scoped_ptr<ScreenCapturer> ScreenCapturer::Create() {
587 return scoped_ptr<VideoFrameCapturer>(new VideoFrameCapturerWin()); 589 return scoped_ptr<ScreenCapturer>(new ScreenCapturerWin());
588 } 590 }
589 591
590 // static 592 // static
591 scoped_ptr<VideoFrameCapturer> VideoFrameCapturer::CreateWithFactory( 593 scoped_ptr<ScreenCapturer> ScreenCapturer::CreateWithFactory(
592 SharedBufferFactory* shared_buffer_factory) { 594 SharedBufferFactory* shared_buffer_factory) {
593 scoped_ptr<VideoFrameCapturerWin> capturer( 595 scoped_ptr<ScreenCapturerWin> capturer(
594 new VideoFrameCapturerWin(shared_buffer_factory)); 596 new ScreenCapturerWin(shared_buffer_factory));
595 return capturer.PassAs<VideoFrameCapturer>(); 597 return capturer.PassAs<ScreenCapturer>();
596 } 598 }
597 599
598 } // namespace remoting 600 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698