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

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

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

Powered by Google App Engine
This is Rietveld 408576698