16b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org/* 26b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved. 36b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org * 46b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org * Use of this source code is governed by a BSD-style license 56b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org * that can be found in the LICENSE file in the root of the source 66b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org * tree. An additional intellectual property rights grant can be found 76b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org * in the file PATENTS. All contributing project authors may 86b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org * be found in the AUTHORS file in the root of the source tree. 96b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org */ 106b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 116b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org#include "webrtc/modules/desktop_capture/win/screen_capturer_win_gdi.h" 126b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 13e38123c801909a3e357f317a6811748aaf81c0ebhenrike@webrtc.org#include <assert.h> 14e38123c801909a3e357f317a6811748aaf81c0ebhenrike@webrtc.org 156b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org#include "webrtc/modules/desktop_capture/desktop_capture_options.h" 166b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org#include "webrtc/modules/desktop_capture/desktop_frame.h" 176b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org#include "webrtc/modules/desktop_capture/desktop_frame_win.h" 186b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org#include "webrtc/modules/desktop_capture/desktop_region.h" 196b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org#include "webrtc/modules/desktop_capture/differ.h" 206b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org#include "webrtc/modules/desktop_capture/mouse_cursor.h" 216b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org#include "webrtc/modules/desktop_capture/win/cursor.h" 226b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org#include "webrtc/modules/desktop_capture/win/desktop.h" 236b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org#include "webrtc/modules/desktop_capture/win/screen_capture_utils.h" 246b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org#include "webrtc/system_wrappers/interface/logging.h" 256b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org#include "webrtc/system_wrappers/interface/tick_util.h" 266b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 276b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.orgnamespace webrtc { 286b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 296b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.orgnamespace { 306b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 316b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org// Constants from dwmapi.h. 326b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.orgconst UINT DWM_EC_DISABLECOMPOSITION = 0; 336b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.orgconst UINT DWM_EC_ENABLECOMPOSITION = 1; 346b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 356b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.orgconst wchar_t kDwmapiLibraryName[] = L"dwmapi.dll"; 366b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 376b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org} // namespace 386b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 396b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.orgScreenCapturerWinGdi::ScreenCapturerWinGdi(const DesktopCaptureOptions& options) 406b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org : callback_(NULL), 416b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org mouse_shape_observer_(NULL), 426b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org current_screen_id_(kFullDesktopScreenId), 436b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org desktop_dc_(NULL), 446b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org memory_dc_(NULL), 456b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org dwmapi_library_(NULL), 466b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org composition_func_(NULL), 476b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org set_thread_execution_state_failed_(false) { 486b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org if (options.disable_effects()) { 496b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org // Load dwmapi.dll dynamically since it is not available on XP. 506b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org if (!dwmapi_library_) 516b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org dwmapi_library_ = LoadLibrary(kDwmapiLibraryName); 526b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 536b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org if (dwmapi_library_) { 546b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org composition_func_ = reinterpret_cast<DwmEnableCompositionFunc>( 556b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org GetProcAddress(dwmapi_library_, "DwmEnableComposition")); 566b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org } 576b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org } 586b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org} 596b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 606b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.orgScreenCapturerWinGdi::~ScreenCapturerWinGdi() { 616b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org if (desktop_dc_) 626b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org ReleaseDC(NULL, desktop_dc_); 636b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org if (memory_dc_) 646b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org DeleteDC(memory_dc_); 656b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 666b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org // Restore Aero. 676b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org if (composition_func_) 686b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org (*composition_func_)(DWM_EC_ENABLECOMPOSITION); 696b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 706b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org if (dwmapi_library_) 716b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org FreeLibrary(dwmapi_library_); 726b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org} 736b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 746b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.orgvoid ScreenCapturerWinGdi::Capture(const DesktopRegion& region) { 756b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org TickTime capture_start_time = TickTime::Now(); 766b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 776b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org queue_.MoveToNextFrame(); 786b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 796b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org // Request that the system not power-down the system, or the display hardware. 806b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org if (!SetThreadExecutionState(ES_DISPLAY_REQUIRED | ES_SYSTEM_REQUIRED)) { 816b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org if (!set_thread_execution_state_failed_) { 826b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org set_thread_execution_state_failed_ = true; 836b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org LOG_F(LS_WARNING) << "Failed to make system & display power assertion: " 846b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org << GetLastError(); 856b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org } 866b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org } 876b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 886b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org // Make sure the GDI capture resources are up-to-date. 896b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org PrepareCaptureResources(); 906b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 916b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org if (!CaptureImage()) { 926b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org callback_->OnCaptureCompleted(NULL); 936b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org return; 946b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org } 956b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 966b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org const DesktopFrame* current_frame = queue_.current_frame(); 976b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org const DesktopFrame* last_frame = queue_.previous_frame(); 986b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org if (last_frame && last_frame->size().equals(current_frame->size())) { 996b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org // Make sure the differencer is set up correctly for these previous and 1006b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org // current screens. 1016b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org if (!differ_.get() || 1026b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org (differ_->width() != current_frame->size().width()) || 1036b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org (differ_->height() != current_frame->size().height()) || 1046b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org (differ_->bytes_per_row() != current_frame->stride())) { 1056b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org differ_.reset(new Differ(current_frame->size().width(), 1066b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org current_frame->size().height(), 1076b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org DesktopFrame::kBytesPerPixel, 1086b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org current_frame->stride())); 1096b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org } 1106b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 1116b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org // Calculate difference between the two last captured frames. 1126b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org DesktopRegion region; 1136b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org differ_->CalcDirtyRegion(last_frame->data(), current_frame->data(), 1146b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org ®ion); 1156b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org helper_.InvalidateRegion(region); 1166b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org } else { 1176b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org // No previous frame is available, or the screen is resized. Invalidate the 1186b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org // whole screen. 1196b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org helper_.InvalidateScreen(current_frame->size()); 1206b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org } 1216b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 1226b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org helper_.set_size_most_recent(current_frame->size()); 1236b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 1246b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org // Emit the current frame. 1256b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org DesktopFrame* frame = queue_.current_frame()->Share(); 1266b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org frame->set_dpi(DesktopVector( 1276b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org GetDeviceCaps(desktop_dc_, LOGPIXELSX), 1286b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org GetDeviceCaps(desktop_dc_, LOGPIXELSY))); 1296b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org frame->mutable_updated_region()->Clear(); 1306b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org helper_.TakeInvalidRegion(frame->mutable_updated_region()); 1316b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org frame->set_capture_time_ms( 1326b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org (TickTime::Now() - capture_start_time).Milliseconds()); 1336b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org callback_->OnCaptureCompleted(frame); 1346b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 1356b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org // Check for cursor shape update. 136e5c55dac67a6e86d2cdb74563d8845847e5ecf18jiayl@webrtc.org if (mouse_shape_observer_) 137e5c55dac67a6e86d2cdb74563d8845847e5ecf18jiayl@webrtc.org CaptureCursor(); 1386b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org} 1396b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 1406b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.orgvoid ScreenCapturerWinGdi::SetMouseShapeObserver( 1416b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org MouseShapeObserver* mouse_shape_observer) { 1426b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org assert(!mouse_shape_observer_); 1436b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org assert(mouse_shape_observer); 1446b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 1456b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org mouse_shape_observer_ = mouse_shape_observer; 1466b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org} 1476b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 1486b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.orgbool ScreenCapturerWinGdi::GetScreenList(ScreenList* screens) { 1496b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org return webrtc::GetScreenList(screens); 1506b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org} 1516b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 1526b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.orgbool ScreenCapturerWinGdi::SelectScreen(ScreenId id) { 1536b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org bool valid = IsScreenValid(id, ¤t_device_key_); 1546b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org if (valid) 1556b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org current_screen_id_ = id; 1566b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org return valid; 1576b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org} 1586b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 1596b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.orgvoid ScreenCapturerWinGdi::Start(Callback* callback) { 1606b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org assert(!callback_); 1616b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org assert(callback); 1626b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 1636b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org callback_ = callback; 1646b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 1656b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org // Vote to disable Aero composited desktop effects while capturing. Windows 1666b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org // will restore Aero automatically if the process exits. This has no effect 1676b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org // under Windows 8 or higher. See crbug.com/124018. 1686b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org if (composition_func_) 1696b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org (*composition_func_)(DWM_EC_DISABLECOMPOSITION); 1706b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org} 1716b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 1726b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.orgvoid ScreenCapturerWinGdi::PrepareCaptureResources() { 1736b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org // Switch to the desktop receiving user input if different from the current 1746b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org // one. 1756b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org scoped_ptr<Desktop> input_desktop(Desktop::GetInputDesktop()); 1766b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org if (input_desktop.get() != NULL && !desktop_.IsSame(*input_desktop)) { 1776b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org // Release GDI resources otherwise SetThreadDesktop will fail. 1786b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org if (desktop_dc_) { 1796b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org ReleaseDC(NULL, desktop_dc_); 1806b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org desktop_dc_ = NULL; 1816b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org } 1826b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 1836b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org if (memory_dc_) { 1846b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org DeleteDC(memory_dc_); 1856b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org memory_dc_ = NULL; 1866b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org } 1876b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 1886b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org // If SetThreadDesktop() fails, the thread is still assigned a desktop. 1896b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org // So we can continue capture screen bits, just from the wrong desktop. 1906b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org desktop_.SetThreadDesktop(input_desktop.release()); 1916b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 1926b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org // Re-assert our vote to disable Aero. 1936b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org // See crbug.com/124018 and crbug.com/129906. 1946b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org if (composition_func_ != NULL) { 1956b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org (*composition_func_)(DWM_EC_DISABLECOMPOSITION); 1966b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org } 1976b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org } 1986b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 1996b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org // If the display bounds have changed then recreate GDI resources. 2006b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org // TODO(wez): Also check for pixel format changes. 2016b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org DesktopRect screen_rect(DesktopRect::MakeXYWH( 2026b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org GetSystemMetrics(SM_XVIRTUALSCREEN), 2036b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org GetSystemMetrics(SM_YVIRTUALSCREEN), 2046b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org GetSystemMetrics(SM_CXVIRTUALSCREEN), 2056b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org GetSystemMetrics(SM_CYVIRTUALSCREEN))); 2066b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org if (!screen_rect.equals(desktop_dc_rect_)) { 2076b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org if (desktop_dc_) { 2086b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org ReleaseDC(NULL, desktop_dc_); 2096b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org desktop_dc_ = NULL; 2106b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org } 2116b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org if (memory_dc_) { 2126b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org DeleteDC(memory_dc_); 2136b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org memory_dc_ = NULL; 2146b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org } 2156b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org desktop_dc_rect_ = DesktopRect(); 2166b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org } 2176b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 2186b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org if (desktop_dc_ == NULL) { 2196b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org assert(memory_dc_ == NULL); 2206b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 2216b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org // Create GDI device contexts to capture from the desktop into memory. 2226b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org desktop_dc_ = GetDC(NULL); 2236b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org if (!desktop_dc_) 2246b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org abort(); 2256b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org memory_dc_ = CreateCompatibleDC(desktop_dc_); 2266b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org if (!memory_dc_) 2276b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org abort(); 2286b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 2296b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org desktop_dc_rect_ = screen_rect; 2306b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 2316b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org // Make sure the frame buffers will be reallocated. 2326b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org queue_.Reset(); 2336b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 2346b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org helper_.ClearInvalidRegion(); 2356b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org } 2366b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org} 2376b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 2386b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.orgbool ScreenCapturerWinGdi::CaptureImage() { 2396b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org DesktopRect screen_rect = 2406b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org GetScreenRect(current_screen_id_, current_device_key_); 2416b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org if (screen_rect.is_empty()) 2426b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org return false; 2436b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 2446b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org DesktopSize size = screen_rect.size(); 2456b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org // If the current buffer is from an older generation then allocate a new one. 2466b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org // Note that we can't reallocate other buffers at this point, since the caller 2476b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org // may still be reading from them. 2486b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org if (!queue_.current_frame() || 2496b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org !queue_.current_frame()->size().equals(screen_rect.size())) { 2506b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org assert(desktop_dc_ != NULL); 2516b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org assert(memory_dc_ != NULL); 2526b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 2536b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org size_t buffer_size = size.width() * size.height() * 2546b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org DesktopFrame::kBytesPerPixel; 2556b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org SharedMemory* shared_memory = callback_->CreateSharedMemory(buffer_size); 2566b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 2576b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org scoped_ptr<DesktopFrame> buffer; 2586b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org buffer.reset( 2596b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org DesktopFrameWin::Create(size, shared_memory, desktop_dc_)); 2606b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org queue_.ReplaceCurrentFrame(buffer.release()); 2616b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org } 2626b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 2636b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org // Select the target bitmap into the memory dc and copy the rect from desktop 2646b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org // to memory. 2656b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org DesktopFrameWin* current = static_cast<DesktopFrameWin*>( 2666b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org queue_.current_frame()->GetUnderlyingFrame()); 2676b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org HGDIOBJ previous_object = SelectObject(memory_dc_, current->bitmap()); 2686b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org if (previous_object != NULL) { 2696b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org BitBlt(memory_dc_, 2706b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 0, 0, screen_rect.width(), screen_rect.height(), 2716b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org desktop_dc_, 2726b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org screen_rect.left(), screen_rect.top(), 2736b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org SRCCOPY | CAPTUREBLT); 2746b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 2756b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org // Select back the previously selected object to that the device contect 2766b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org // could be destroyed independently of the bitmap if needed. 2776b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org SelectObject(memory_dc_, previous_object); 2786b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org } 2796b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org return true; 2806b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org} 2816b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 2826b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.orgvoid ScreenCapturerWinGdi::CaptureCursor() { 283e5c55dac67a6e86d2cdb74563d8845847e5ecf18jiayl@webrtc.org assert(mouse_shape_observer_); 284e5c55dac67a6e86d2cdb74563d8845847e5ecf18jiayl@webrtc.org 2856b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org CURSORINFO cursor_info; 2866b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org cursor_info.cbSize = sizeof(CURSORINFO); 2876b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org if (!GetCursorInfo(&cursor_info)) { 2886b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org LOG_F(LS_ERROR) << "Unable to get cursor info. Error = " << GetLastError(); 2896b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org return; 2906b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org } 2916b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 2926b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org // Note that |cursor_info.hCursor| does not need to be freed. 2936b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org scoped_ptr<MouseCursor> cursor_image( 2946b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org CreateMouseCursorFromHCursor(desktop_dc_, cursor_info.hCursor)); 2956b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org if (!cursor_image.get()) 2966b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org return; 2976b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 2986b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org scoped_ptr<MouseCursorShape> cursor(new MouseCursorShape); 2996b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org cursor->hotspot = cursor_image->hotspot(); 3006b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org cursor->size = cursor_image->image()->size(); 3016b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org uint8_t* current_row = cursor_image->image()->data(); 3026b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org for (int y = 0; y < cursor_image->image()->size().height(); ++y) { 3036b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org cursor->data.append(current_row, 3046b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org current_row + cursor_image->image()->size().width() * 3056b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org DesktopFrame::kBytesPerPixel); 3066b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org current_row += cursor_image->image()->stride(); 3076b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org } 3086b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 3096b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org // Compare the current cursor with the last one we sent to the client. If 3106b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org // they're the same, then don't bother sending the cursor again. 3116b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org if (last_cursor_.size.equals(cursor->size) && 3126b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org last_cursor_.hotspot.equals(cursor->hotspot) && 3136b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org last_cursor_.data == cursor->data) { 3146b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org return; 3156b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org } 3166b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 3176b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org LOG(LS_VERBOSE) << "Sending updated cursor: " << cursor->size.width() << "x" 3186b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org << cursor->size.height(); 3196b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 3206b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org // Record the last cursor image that we sent to the client. 3216b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org last_cursor_ = *cursor; 3226b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 323e5c55dac67a6e86d2cdb74563d8845847e5ecf18jiayl@webrtc.org mouse_shape_observer_->OnCursorShapeChanged(cursor.release()); 3246b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org} 3256b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 3266b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org} // namespace webrtc 327