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

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

Powered by Google App Engine
This is Rietveld 408576698