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

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
90 // notifies |delegate_|.
91 void CaptureRegion(const SkRegion& region,
92 const base::Time& capture_start_time);
93
94 // Captures the current screen contents into the current buffer. 66 // Captures the current screen contents into the current buffer.
95 void CaptureImage(); 67 void CaptureImage();
96 68
97 // Expand the cursor shape to add a white outline for visibility against 69 // Expand the cursor shape to add a white outline for visibility against
98 // dark backgrounds. 70 // dark backgrounds.
99 void AddCursorOutline(int width, int height, uint32* dst); 71 void AddCursorOutline(int width, int height, uint32* dst);
100 72
101 // Capture the current cursor shape. 73 // Capture the current cursor shape.
102 void CaptureCursor(); 74 void CaptureCursor();
103 75
104 Delegate* delegate_; 76 Callback* callback_;
77 MouseShapeObserver* mouse_shape_observer_;
105 78
106 // A thread-safe list of invalid rectangles, and the size of the most 79 // A thread-safe list of invalid rectangles, and the size of the most
107 // recently captured screen. 80 // recently captured screen.
108 ScreenCapturerHelper helper_; 81 ScreenCapturerHelper helper_;
109 82
110 // Snapshot of the last cursor bitmap we sent to the client. This is used 83 // 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 84 // to diff against the current cursor so we only send a cursor-change
112 // message when the shape has changed. 85 // message when the shape has changed.
113 MouseCursorShape last_cursor_; 86 MouseCursorShape last_cursor_;
114 87
(...skipping 14 matching lines...) Expand all
129 102
130 base::ScopedNativeLibrary dwmapi_library_; 103 base::ScopedNativeLibrary dwmapi_library_;
131 DwmEnableCompositionFunc composition_func_; 104 DwmEnableCompositionFunc composition_func_;
132 105
133 // Used to suppress duplicate logging of SetThreadExecutionState errors. 106 // Used to suppress duplicate logging of SetThreadExecutionState errors.
134 bool set_thread_execution_state_failed_; 107 bool set_thread_execution_state_failed_;
135 108
136 DISALLOW_COPY_AND_ASSIGN(ScreenCapturerWin); 109 DISALLOW_COPY_AND_ASSIGN(ScreenCapturerWin);
137 }; 110 };
138 111
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) 112 ScreenCapturerWin::ScreenCapturerWin(bool disable_aero)
205 : delegate_(NULL), 113 : callback_(NULL),
114 mouse_shape_observer_(NULL),
206 desktop_dc_rect_(SkIRect::MakeEmpty()), 115 desktop_dc_rect_(SkIRect::MakeEmpty()),
207 composition_func_(NULL), 116 composition_func_(NULL),
208 set_thread_execution_state_failed_(false) { 117 set_thread_execution_state_failed_(false) {
209 if (disable_aero) { 118 if (disable_aero) {
210 // Load dwmapi.dll dynamically since it is not available on XP. 119 // Load dwmapi.dll dynamically since it is not available on XP.
211 if (!dwmapi_library_.is_valid()) { 120 if (!dwmapi_library_.is_valid()) {
212 base::FilePath path(base::GetNativeLibraryName( 121 base::FilePath path(base::GetNativeLibraryName(
213 UTF8ToUTF16(kDwmapiLibraryName))); 122 UTF8ToUTF16(kDwmapiLibraryName)));
214 dwmapi_library_.Reset(base::LoadNativeLibrary(path, NULL)); 123 dwmapi_library_.Reset(base::LoadNativeLibrary(path, NULL));
215 } 124 }
216 125
217 if (dwmapi_library_.is_valid() && composition_func_ == NULL) { 126 if (dwmapi_library_.is_valid() && composition_func_ == NULL) {
218 composition_func_ = reinterpret_cast<DwmEnableCompositionFunc>( 127 composition_func_ = reinterpret_cast<DwmEnableCompositionFunc>(
219 dwmapi_library_.GetFunctionPointer("DwmEnableComposition")); 128 dwmapi_library_.GetFunctionPointer("DwmEnableComposition"));
220 } 129 }
221 } 130 }
222 } 131 }
223 132
224 ScreenCapturerWin::~ScreenCapturerWin() { 133 ScreenCapturerWin::~ScreenCapturerWin() {
225 // Restore Aero. 134 // Restore Aero.
226 if (composition_func_ != NULL) { 135 if (composition_func_ != NULL) {
227 (*composition_func_)(DWM_EC_ENABLECOMPOSITION); 136 (*composition_func_)(DWM_EC_ENABLECOMPOSITION);
228 } 137 }
229
230 delegate_ = NULL;
231 } 138 }
232 139
233 void ScreenCapturerWin::CaptureFrame() { 140 void ScreenCapturerWin::Capture(const webrtc::DesktopRegion& region) {
234 base::Time capture_start_time = base::Time::Now(); 141 base::Time capture_start_time = base::Time::Now();
235 142
143 queue_.MoveToNextFrame();
144
236 // Request that the system not power-down the system, or the display hardware. 145 // Request that the system not power-down the system, or the display hardware.
237 if (!SetThreadExecutionState(ES_DISPLAY_REQUIRED | ES_SYSTEM_REQUIRED)) { 146 if (!SetThreadExecutionState(ES_DISPLAY_REQUIRED | ES_SYSTEM_REQUIRED)) {
238 if (!set_thread_execution_state_failed_) { 147 if (!set_thread_execution_state_failed_) {
239 set_thread_execution_state_failed_ = true; 148 set_thread_execution_state_failed_ = true;
240 LOG_GETLASTERROR(WARNING) 149 LOG_GETLASTERROR(WARNING)
241 << "Failed to make system & display power assertion"; 150 << "Failed to make system & display power assertion";
242 } 151 }
243 } 152 }
244 153
245 // Make sure the GDI capture resources are up-to-date. 154 // Make sure the GDI capture resources are up-to-date.
246 PrepareCaptureResources(); 155 PrepareCaptureResources();
247 156
248 // Copy screen bits to the current buffer. 157 // Copy screen bits to the current buffer.
249 CaptureImage(); 158 CaptureImage();
250 159
251 const ScreenCaptureFrame* current_buffer = queue_.current_frame(); 160 const webrtc::DesktopFrame* current_frame = queue_.current_frame();
252 const ScreenCaptureFrame* last_buffer = queue_.previous_frame(); 161 const webrtc::DesktopFrame* last_frame = queue_.previous_frame();
253 if (last_buffer) { 162 if (last_frame) {
254 // Make sure the differencer is set up correctly for these previous and 163 // Make sure the differencer is set up correctly for these previous and
255 // current screens. 164 // current screens.
256 if (!differ_.get() || 165 if (!differ_.get() ||
257 (differ_->width() != current_buffer->dimensions().width()) || 166 (differ_->width() != current_frame->size().width()) ||
258 (differ_->height() != current_buffer->dimensions().height()) || 167 (differ_->height() != current_frame->size().height()) ||
259 (differ_->bytes_per_row() != current_buffer->bytes_per_row())) { 168 (differ_->bytes_per_row() != current_frame->stride())) {
260 differ_.reset(new Differ(current_buffer->dimensions().width(), 169 differ_.reset(new Differ(current_frame->size().width(),
261 current_buffer->dimensions().height(), 170 current_frame->size().height(),
262 ScreenCaptureData::kBytesPerPixel, 171 webrtc::DesktopFrame::kBytesPerPixel,
263 current_buffer->bytes_per_row())); 172 current_frame->stride()));
264 } 173 }
265 174
266 // Calculate difference between the two last captured frames. 175 // Calculate difference between the two last captured frames.
267 SkRegion region; 176 webrtc::DesktopRegion region;
268 differ_->CalcDirtyRegion(last_buffer->pixels(), current_buffer->pixels(), 177 differ_->CalcDirtyRegion(last_frame->data(), current_frame->data(),
269 &region); 178 &region);
270 helper_.InvalidateRegion(region); 179 helper_.InvalidateRegion(region);
271 } else { 180 } else {
272 // No previous frame is available. Invalidate the whole screen. 181 // No previous frame is available. Invalidate the whole screen.
273 helper_.InvalidateScreen(current_buffer->dimensions()); 182 helper_.InvalidateScreen(current_frame->size());
274 } 183 }
275 184
276 // Wrap the captured frame into ScreenCaptureData structure and invoke 185 helper_.set_size_most_recent(current_frame->size());
277 // the completion callback. 186
278 SkRegion invalid_region; 187 // Emit the current frame.
279 helper_.SwapInvalidRegion(&invalid_region); 188 webrtc::DesktopFrame* frame = queue_.current_frame()->Share();
280 CaptureRegion(invalid_region, capture_start_time); 189 frame->set_dpi(webrtc::DesktopVector(
190 GetDeviceCaps(*desktop_dc_, LOGPIXELSX),
191 GetDeviceCaps(*desktop_dc_, LOGPIXELSY)));
192 frame->mutable_updated_region()->Clear();
193 helper_.TakeInvalidRegion(frame->mutable_updated_region());
194 frame->set_capture_time_ms(
195 (base::Time::Now() - capture_start_time).InMillisecondsRoundedUp());
196 callback_->OnCaptureCompleted(frame);
281 197
282 // Check for cursor shape update. 198 // Check for cursor shape update.
283 CaptureCursor(); 199 CaptureCursor();
284 } 200 }
285 201
286 void ScreenCapturerWin::Start(Delegate* delegate) { 202 void ScreenCapturerWin::SetMouseShapeObserver(
287 DCHECK(delegate_ == NULL); 203 MouseShapeObserver* mouse_shape_observer) {
204 DCHECK(!mouse_shape_observer_);
205 DCHECK(mouse_shape_observer);
288 206
289 delegate_ = delegate; 207 mouse_shape_observer_ = mouse_shape_observer;
208 }
209
210 void ScreenCapturerWin::Start(Callback* callback) {
211 DCHECK(!callback_);
212 DCHECK(callback);
213
214 callback_ = callback;
290 215
291 // Vote to disable Aero composited desktop effects while capturing. Windows 216 // Vote to disable Aero composited desktop effects while capturing. Windows
292 // will restore Aero automatically if the process exits. This has no effect 217 // will restore Aero automatically if the process exits. This has no effect
293 // under Windows 8 or higher. See crbug.com/124018. 218 // under Windows 8 or higher. See crbug.com/124018.
294 if (composition_func_ != NULL) { 219 if (composition_func_ != NULL) {
295 (*composition_func_)(DWM_EC_DISABLECOMPOSITION); 220 (*composition_func_)(DWM_EC_DISABLECOMPOSITION);
296 } 221 }
297 } 222 }
298 223
299 void ScreenCapturerWin::PrepareCaptureResources() { 224 void ScreenCapturerWin::PrepareCaptureResources() {
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
331 256
332 if (desktop_dc_.get() == NULL) { 257 if (desktop_dc_.get() == NULL) {
333 DCHECK(memory_dc_.Get() == NULL); 258 DCHECK(memory_dc_.Get() == NULL);
334 259
335 // Create GDI device contexts to capture from the desktop into memory. 260 // Create GDI device contexts to capture from the desktop into memory.
336 desktop_dc_.reset(new base::win::ScopedGetDC(NULL)); 261 desktop_dc_.reset(new base::win::ScopedGetDC(NULL));
337 memory_dc_.Set(CreateCompatibleDC(*desktop_dc_)); 262 memory_dc_.Set(CreateCompatibleDC(*desktop_dc_));
338 desktop_dc_rect_ = screen_rect; 263 desktop_dc_rect_ = screen_rect;
339 264
340 // Make sure the frame buffers will be reallocated. 265 // Make sure the frame buffers will be reallocated.
341 queue_.SetAllFramesNeedUpdate(); 266 queue_.Reset();
342 267
343 helper_.ClearInvalidRegion(); 268 helper_.ClearInvalidRegion();
344 } 269 }
345 } 270 }
346 271
347 void ScreenCapturerWin::CaptureRegion(
348 const SkRegion& region,
349 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 }
371
372 void ScreenCapturerWin::CaptureImage() { 272 void ScreenCapturerWin::CaptureImage() {
373 // If the current buffer is from an older generation then allocate a new one. 273 // 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 274 // Note that we can't reallocate other buffers at this point, since the caller
375 // may still be reading from them. 275 // may still be reading from them.
376 if (queue_.current_frame_needs_update()) { 276 if (!queue_.current_frame()) {
377 DCHECK(desktop_dc_.get() != NULL); 277 DCHECK(desktop_dc_.get() != NULL);
378 DCHECK(memory_dc_.Get() != NULL); 278 DCHECK(memory_dc_.Get() != NULL);
379 279
380 SkISize size = SkISize::Make(desktop_dc_rect_.width(), 280 webrtc::DesktopSize size = webrtc::DesktopSize(
381 desktop_dc_rect_.height()); 281 desktop_dc_rect_.width(), desktop_dc_rect_.height());
382 scoped_ptr<ScreenCaptureFrameWin> buffer( 282
383 new ScreenCaptureFrameWin(*desktop_dc_, size, delegate_)); 283 size_t buffer_size = size.width() * size.height() *
384 queue_.ReplaceCurrentFrame(buffer.PassAs<ScreenCaptureFrame>()); 284 webrtc::DesktopFrame::kBytesPerPixel;
285 webrtc::SharedMemory* shared_memory =
286 callback_->CreateSharedMemory(buffer_size);
287 scoped_ptr<webrtc::DesktopFrameWin> buffer(
288 webrtc::DesktopFrameWin::Create(size, shared_memory, *desktop_dc_));
289 queue_.ReplaceCurrentFrame(buffer.PassAs<webrtc::DesktopFrame>());
385 } 290 }
386 291
387 // Select the target bitmap into the memory dc and copy the rect from desktop 292 // Select the target bitmap into the memory dc and copy the rect from desktop
388 // to memory. 293 // to memory.
389 ScreenCaptureFrameWin* current = static_cast<ScreenCaptureFrameWin*>( 294 webrtc::DesktopFrameWin* current = static_cast<webrtc::DesktopFrameWin*>(
390 queue_.current_frame()); 295 queue_.current_frame()->GetUnderlyingFrame());
391 HGDIOBJ previous_object = SelectObject(memory_dc_, current->GetBitmap()); 296 HGDIOBJ previous_object = SelectObject(memory_dc_, current->bitmap());
392 if (previous_object != NULL) { 297 if (previous_object != NULL) {
393 BitBlt(memory_dc_, 298 BitBlt(memory_dc_,
394 0, 0, desktop_dc_rect_.width(), desktop_dc_rect_.height(), 299 0, 0, desktop_dc_rect_.width(), desktop_dc_rect_.height(),
395 *desktop_dc_, 300 *desktop_dc_,
396 desktop_dc_rect_.x(), desktop_dc_rect_.y(), 301 desktop_dc_rect_.x(), desktop_dc_rect_.y(),
397 SRCCOPY | CAPTUREBLT); 302 SRCCOPY | CAPTUREBLT);
398 303
399 // Select back the previously selected object to that the device contect 304 // Select back the previously selected object to that the device contect
400 // could be destroyed independently of the bitmap if needed. 305 // could be destroyed independently of the bitmap if needed.
401 SelectObject(memory_dc_, previous_object); 306 SelectObject(memory_dc_, previous_object);
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
472 } 377 }
473 378
474 int width = bitmap.bmWidth; 379 int width = bitmap.bmWidth;
475 int height = bitmap.bmHeight; 380 int height = bitmap.bmHeight;
476 // For non-color cursors, the mask contains both an AND and an XOR mask and 381 // 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 382 // the height includes both. Thus, the width is correct, but we need to
478 // divide by 2 to get the correct mask height. 383 // divide by 2 to get the correct mask height.
479 if (!color_bitmap) { 384 if (!color_bitmap) {
480 height /= 2; 385 height /= 2;
481 } 386 }
482 int data_size = height * width * ScreenCaptureData::kBytesPerPixel; 387 int data_size = height * width * webrtc::DesktopFrame::kBytesPerPixel;
483 388
484 scoped_ptr<MouseCursorShape> cursor(new MouseCursorShape()); 389 scoped_ptr<MouseCursorShape> cursor(new MouseCursorShape());
485 cursor->data.resize(data_size); 390 cursor->data.resize(data_size);
486 uint8* cursor_dst_data = 391 uint8* cursor_dst_data =
487 reinterpret_cast<uint8*>(string_as_array(&cursor->data)); 392 reinterpret_cast<uint8*>(string_as_array(&cursor->data));
488 393
489 // Copy/convert cursor bitmap into format needed by chromotocol. 394 // Copy/convert cursor bitmap into format needed by chromotocol.
490 int row_bytes = bitmap.bmWidthBytes; 395 int row_bytes = bitmap.bmWidthBytes;
491 if (color_bitmap) { 396 if (color_bitmap) {
492 if (bitmap.bmPlanes != 1 || bitmap.bmBitsPixel != 32) { 397 if (bitmap.bmPlanes != 1 || bitmap.bmBitsPixel != 32) {
493 VLOG(3) << "Unsupported color cursor format. Error = " << GetLastError(); 398 VLOG(3) << "Unsupported color cursor format. Error = " << GetLastError();
494 return; 399 return;
495 } 400 }
496 401
497 // Copy across colour cursor imagery. 402 // Copy across colour cursor imagery.
498 // MouseCursorShape stores imagery top-down, and premultiplied 403 // MouseCursorShape stores imagery top-down, and premultiplied
499 // by the alpha channel, whereas windows stores them bottom-up 404 // by the alpha channel, whereas windows stores them bottom-up
500 // and not premultiplied. 405 // and not premultiplied.
501 uint8* cursor_src_data = reinterpret_cast<uint8*>(bitmap.bmBits); 406 uint8* cursor_src_data = reinterpret_cast<uint8*>(bitmap.bmBits);
502 uint8* src = cursor_src_data + ((height - 1) * row_bytes); 407 uint8* src = cursor_src_data + ((height - 1) * row_bytes);
503 uint8* dst = cursor_dst_data; 408 uint8* dst = cursor_dst_data;
504 for (int row = 0; row < height; ++row) { 409 for (int row = 0; row < height; ++row) {
505 for (int column = 0; column < width; ++column) { 410 for (int column = 0; column < width; ++column) {
506 dst[0] = SkAlphaMul(src[0], src[3]); 411 dst[0] = SkAlphaMul(src[0], src[3]);
507 dst[1] = SkAlphaMul(src[1], src[3]); 412 dst[1] = SkAlphaMul(src[1], src[3]);
508 dst[2] = SkAlphaMul(src[2], src[3]); 413 dst[2] = SkAlphaMul(src[2], src[3]);
509 dst[3] = src[3]; 414 dst[3] = src[3];
510 dst += ScreenCaptureData::kBytesPerPixel; 415 dst += webrtc::DesktopFrame::kBytesPerPixel;
511 src += ScreenCaptureData::kBytesPerPixel; 416 src += webrtc::DesktopFrame::kBytesPerPixel;
512 } 417 }
513 src -= row_bytes + (width * ScreenCaptureData::kBytesPerPixel); 418 src -= row_bytes + (width * webrtc::DesktopFrame::kBytesPerPixel);
514 } 419 }
515 } else { 420 } else {
516 if (bitmap.bmPlanes != 1 || bitmap.bmBitsPixel != 1) { 421 if (bitmap.bmPlanes != 1 || bitmap.bmBitsPixel != 1) {
517 VLOG(3) << "Unsupported cursor mask format. Error = " << GetLastError(); 422 VLOG(3) << "Unsupported cursor mask format. Error = " << GetLastError();
518 return; 423 return;
519 } 424 }
520 425
521 // x2 because there are 2 masks in the bitmap: AND and XOR. 426 // x2 because there are 2 masks in the bitmap: AND and XOR.
522 int mask_bytes = height * row_bytes * 2; 427 int mask_bytes = height * row_bytes * 2;
523 scoped_ptr<uint8[]> mask(new uint8[mask_bytes]); 428 scoped_ptr<uint8[]> mask(new uint8[mask_bytes]);
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
560 AddCursorOutline(width, height, 465 AddCursorOutline(width, height,
561 reinterpret_cast<uint32*>(cursor_dst_data)); 466 reinterpret_cast<uint32*>(cursor_dst_data));
562 } 467 }
563 } 468 }
564 469
565 cursor->size.set(width, height); 470 cursor->size.set(width, height);
566 cursor->hotspot.set(hotspot_x, hotspot_y); 471 cursor->hotspot.set(hotspot_x, hotspot_y);
567 472
568 // Compare the current cursor with the last one we sent to the client. If 473 // 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. 474 // they're the same, then don't bother sending the cursor again.
570 if (last_cursor_.size == cursor->size && 475 if (last_cursor_.size.equals(cursor->size) &&
571 last_cursor_.hotspot == cursor->hotspot && 476 last_cursor_.hotspot.equals(cursor->hotspot) &&
572 last_cursor_.data == cursor->data) { 477 last_cursor_.data == cursor->data) {
573 return; 478 return;
574 } 479 }
575 480
576 VLOG(3) << "Sending updated cursor: " << width << "x" << height; 481 VLOG(3) << "Sending updated cursor: " << width << "x" << height;
577 482
578 // Record the last cursor image that we sent to the client. 483 // Record the last cursor image that we sent to the client.
579 last_cursor_ = *cursor; 484 last_cursor_ = *cursor;
580 485
581 delegate_->OnCursorShapeChanged(cursor.Pass()); 486 if (mouse_shape_observer_)
487 mouse_shape_observer_->OnCursorShapeChanged(cursor.Pass());
582 } 488 }
583 489
584 } // namespace 490 } // namespace
585 491
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 492 // static
596 scoped_ptr<ScreenCapturer> ScreenCapturer::Create() { 493 scoped_ptr<ScreenCapturer> ScreenCapturer::Create() {
597 return CreateWithDisableAero(true); 494 return CreateWithDisableAero(true);
598 } 495 }
599 496
600 // static 497 // static
601 scoped_ptr<ScreenCapturer> ScreenCapturer::CreateWithDisableAero( 498 scoped_ptr<ScreenCapturer> ScreenCapturer::CreateWithDisableAero(
602 bool disable_aero) { 499 bool disable_aero) {
603 return scoped_ptr<ScreenCapturer>(new ScreenCapturerWin(disable_aero)); 500 return scoped_ptr<ScreenCapturer>(new ScreenCapturerWin(disable_aero));
604 } 501 }
605 502
606 } // namespace media 503 } // namespace media
OLDNEW
« no previous file with comments | « media/video/capture/screen/screen_capturer_unittest.cc ('k') | media/video/capture/screen/screen_capturer_x11.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698