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_magnifier.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.org// kMagnifierWindowClass has to be "Magnifier" according to the Magnification 306b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org// API. The other strings can be anything. 316b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.orgstatic LPCTSTR kMagnifierHostClass = L"ScreenCapturerWinMagnifierHost"; 326b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.orgstatic LPCTSTR kHostWindowName = L"MagnifierHost"; 336b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.orgstatic LPCTSTR kMagnifierWindowClass = L"Magnifier"; 346b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.orgstatic LPCTSTR kMagnifierWindowName = L"MagnifierWindow"; 356b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 366b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.orgAtomic32 ScreenCapturerWinMagnifier::tls_index_(TLS_OUT_OF_INDEXES); 376b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 386b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.orgScreenCapturerWinMagnifier::ScreenCapturerWinMagnifier( 396b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org scoped_ptr<ScreenCapturer> fallback_capturer) 406b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org : fallback_capturer_(fallback_capturer.Pass()), 416b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org fallback_capturer_started_(false), 426b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org callback_(NULL), 436b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org current_screen_id_(kFullDesktopScreenId), 446b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org excluded_window_(NULL), 456b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org set_thread_execution_state_failed_(false), 466b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org desktop_dc_(NULL), 476b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org mag_lib_handle_(NULL), 486b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org mag_initialize_func_(NULL), 496b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org mag_uninitialize_func_(NULL), 506b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org set_window_source_func_(NULL), 516b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org set_window_filter_list_func_(NULL), 526b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org set_image_scaling_callback_func_(NULL), 536b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org host_window_(NULL), 546b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org magnifier_window_(NULL), 556b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org magnifier_initialized_(false), 566b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org magnifier_capture_succeeded_(true) { 576b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org} 586b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 596b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.orgScreenCapturerWinMagnifier::~ScreenCapturerWinMagnifier() { 606b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org // DestroyWindow must be called before MagUninitialize. magnifier_window_ is 616b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org // destroyed automatically when host_window_ is destroyed. 626b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org if (host_window_) 636b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org DestroyWindow(host_window_); 646b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 656b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org if (magnifier_initialized_) 666b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org mag_uninitialize_func_(); 676b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 686b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org if (mag_lib_handle_) 696b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org FreeLibrary(mag_lib_handle_); 706b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 716b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org if (desktop_dc_) 726b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org ReleaseDC(NULL, desktop_dc_); 736b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org} 746b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 756b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.orgvoid ScreenCapturerWinMagnifier::Start(Callback* callback) { 766b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org assert(!callback_); 776b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org assert(callback); 786b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org callback_ = callback; 796b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 806b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org InitializeMagnifier(); 816b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org} 826b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 836b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.orgvoid ScreenCapturerWinMagnifier::Capture(const DesktopRegion& region) { 846b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org TickTime capture_start_time = TickTime::Now(); 856b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 866b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org queue_.MoveToNextFrame(); 876b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 886b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org // Request that the system not power-down the system, or the display hardware. 896b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org if (!SetThreadExecutionState(ES_DISPLAY_REQUIRED | ES_SYSTEM_REQUIRED)) { 906b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org if (!set_thread_execution_state_failed_) { 916b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org set_thread_execution_state_failed_ = true; 926b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org LOG_F(LS_WARNING) << "Failed to make system & display power assertion: " 936b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org << GetLastError(); 946b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org } 956b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org } 966b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org // Switch to the desktop receiving user input if different from the current 976b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org // one. 986b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org scoped_ptr<Desktop> input_desktop(Desktop::GetInputDesktop()); 996b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org if (input_desktop.get() != NULL && !desktop_.IsSame(*input_desktop)) { 1006b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org // Release GDI resources otherwise SetThreadDesktop will fail. 1016b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org if (desktop_dc_) { 1026b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org ReleaseDC(NULL, desktop_dc_); 1036b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org desktop_dc_ = NULL; 1046b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org } 1056b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org // If SetThreadDesktop() fails, the thread is still assigned a desktop. 1066b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org // So we can continue capture screen bits, just from the wrong desktop. 1076b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org desktop_.SetThreadDesktop(input_desktop.release()); 1086b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org } 1096b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 1106b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org bool succeeded = false; 1116b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 1126b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org // Do not try to use the magnfiier if it's capturing non-primary screen, or it 1136b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org // failed before. 1146b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org if (magnifier_initialized_ && IsCapturingPrimaryScreenOnly() && 1156b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org magnifier_capture_succeeded_) { 1166b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org DesktopRect rect = GetScreenRect(current_screen_id_, current_device_key_); 1176b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org CreateCurrentFrameIfNecessary(rect.size()); 1186b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 1196b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org // CaptureImage may fail in some situations, e.g. windows8 metro mode. 1206b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org succeeded = CaptureImage(rect); 1216b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org } 1226b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 1236b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org // Defer to the fallback capturer if magnifier capturer did not work. 1246b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org if (!succeeded) { 1256b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org LOG_F(LS_WARNING) << "Switching to the fallback screen capturer."; 1266b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org StartFallbackCapturer(); 1276b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org fallback_capturer_->Capture(region); 1286b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org return; 1296b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org } 1306b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 1316b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org const DesktopFrame* current_frame = queue_.current_frame(); 1326b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org const DesktopFrame* last_frame = queue_.previous_frame(); 1336b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org if (last_frame && last_frame->size().equals(current_frame->size())) { 1346b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org // Make sure the differencer is set up correctly for these previous and 1356b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org // current screens. 1366b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org if (!differ_.get() || (differ_->width() != current_frame->size().width()) || 1376b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org (differ_->height() != current_frame->size().height()) || 1386b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org (differ_->bytes_per_row() != current_frame->stride())) { 1396b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org differ_.reset(new Differ(current_frame->size().width(), 1406b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org current_frame->size().height(), 1416b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org DesktopFrame::kBytesPerPixel, 1426b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org current_frame->stride())); 1436b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org } 1446b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 1456b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org // Calculate difference between the two last captured frames. 1466b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org DesktopRegion region; 1476b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org differ_->CalcDirtyRegion( 1486b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org last_frame->data(), current_frame->data(), ®ion); 1496b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org helper_.InvalidateRegion(region); 1506b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org } else { 1516b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org // No previous frame is available, or the screen is resized. Invalidate the 1526b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org // whole screen. 1536b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org helper_.InvalidateScreen(current_frame->size()); 1546b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org } 1556b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 1566b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org helper_.set_size_most_recent(current_frame->size()); 1576b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 1586b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org // Emit the current frame. 1596b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org DesktopFrame* frame = queue_.current_frame()->Share(); 1606b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org frame->set_dpi(DesktopVector(GetDeviceCaps(desktop_dc_, LOGPIXELSX), 1616b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org GetDeviceCaps(desktop_dc_, LOGPIXELSY))); 1626b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org frame->mutable_updated_region()->Clear(); 1636b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org helper_.TakeInvalidRegion(frame->mutable_updated_region()); 1646b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org frame->set_capture_time_ms( 1656b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org (TickTime::Now() - capture_start_time).Milliseconds()); 1666b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org callback_->OnCaptureCompleted(frame); 1676b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org} 1686b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 1696b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.orgvoid ScreenCapturerWinMagnifier::SetMouseShapeObserver( 1706b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org MouseShapeObserver* mouse_shape_observer) { 1716b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org assert(false); // NOTREACHED(); 1726b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org} 1736b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 1746b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.orgbool ScreenCapturerWinMagnifier::GetScreenList(ScreenList* screens) { 1756b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org return webrtc::GetScreenList(screens); 1766b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org} 1776b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 1786b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.orgbool ScreenCapturerWinMagnifier::SelectScreen(ScreenId id) { 1796b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org bool valid = IsScreenValid(id, ¤t_device_key_); 1806b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 1816b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org // Set current_screen_id_ even if the fallback capturer is being used, so we 1826b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org // can switch back to the magnifier when possible. 1836b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org if (valid) 1846b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org current_screen_id_ = id; 1856b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 1866b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org if (fallback_capturer_started_) 1876b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org fallback_capturer_->SelectScreen(id); 1886b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 1896b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org return valid; 1906b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org} 1916b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 1926b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.orgvoid ScreenCapturerWinMagnifier::SetExcludedWindow(WindowId excluded_window) { 1936b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org excluded_window_ = (HWND)excluded_window; 1946b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org if (excluded_window_ && magnifier_initialized_) { 1956b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org set_window_filter_list_func_( 1966b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org magnifier_window_, MW_FILTERMODE_EXCLUDE, 1, &excluded_window_); 1976b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org } 1986b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org} 1996b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 2006b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.orgbool ScreenCapturerWinMagnifier::CaptureImage(const DesktopRect& rect) { 2016b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org assert(magnifier_initialized_); 2026b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 2036b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org // Set the magnifier control to cover the captured rect. The content of the 2046b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org // magnifier control will be the captured image. 2056b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org BOOL result = SetWindowPos(magnifier_window_, 2066b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org NULL, 2076b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org rect.left(), rect.top(), 2086b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org rect.width(), rect.height(), 2096b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 0); 2106b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org if (!result) { 2116b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org LOG_F(LS_WARNING) << "Failed to call SetWindowPos: " << GetLastError() 2126b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org << ". Rect = {" << rect.left() << ", " << rect.top() 2136b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org << ", " << rect.right() << ", " << rect.bottom() << "}"; 2146b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org return false; 2156b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org } 2166b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 2176b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org magnifier_capture_succeeded_ = false; 2186b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 2196b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org RECT native_rect = {rect.left(), rect.top(), rect.right(), rect.bottom()}; 2206b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 2216b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org // OnCaptured will be called via OnMagImageScalingCallback and fill in the 2226b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org // frame before set_window_source_func_ returns. 2236b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org result = set_window_source_func_(magnifier_window_, native_rect); 2246b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 2256b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org if (!result) { 2266b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org LOG_F(LS_WARNING) << "Failed to call MagSetWindowSource: " << GetLastError() 2276b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org << ". Rect = {" << rect.left() << ", " << rect.top() 2286b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org << ", " << rect.right() << ", " << rect.bottom() << "}"; 2296b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org return false; 2306b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org } 2316b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 2326b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org return magnifier_capture_succeeded_; 2336b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org} 2346b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 2356b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.orgBOOL ScreenCapturerWinMagnifier::OnMagImageScalingCallback( 2366b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org HWND hwnd, 2376b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org void* srcdata, 2386b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org MAGIMAGEHEADER srcheader, 2396b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org void* destdata, 2406b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org MAGIMAGEHEADER destheader, 2416b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org RECT unclipped, 2426b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org RECT clipped, 2436b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org HRGN dirty) { 2446b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org assert(tls_index_.Value() != TLS_OUT_OF_INDEXES); 2456b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 2466b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org ScreenCapturerWinMagnifier* owner = 2476b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org reinterpret_cast<ScreenCapturerWinMagnifier*>( 2486b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org TlsGetValue(tls_index_.Value())); 2496b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 2506b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org owner->OnCaptured(srcdata, srcheader); 2516b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 2526b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org return TRUE; 2536b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org} 2546b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 2556b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.orgbool ScreenCapturerWinMagnifier::InitializeMagnifier() { 2566b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org assert(!magnifier_initialized_); 2576b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 2586b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org desktop_dc_ = GetDC(NULL); 2596b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 2606b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org mag_lib_handle_ = LoadLibrary(L"Magnification.dll"); 2616b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org if (!mag_lib_handle_) 2626b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org return false; 2636b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 2646b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org // Initialize Magnification API function pointers. 2656b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org mag_initialize_func_ = reinterpret_cast<MagInitializeFunc>( 2666b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org GetProcAddress(mag_lib_handle_, "MagInitialize")); 2676b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org mag_uninitialize_func_ = reinterpret_cast<MagUninitializeFunc>( 2686b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org GetProcAddress(mag_lib_handle_, "MagUninitialize")); 2696b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org set_window_source_func_ = reinterpret_cast<MagSetWindowSourceFunc>( 2706b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org GetProcAddress(mag_lib_handle_, "MagSetWindowSource")); 2716b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org set_window_filter_list_func_ = reinterpret_cast<MagSetWindowFilterListFunc>( 2726b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org GetProcAddress(mag_lib_handle_, "MagSetWindowFilterList")); 2736b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org set_image_scaling_callback_func_ = 2746b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org reinterpret_cast<MagSetImageScalingCallbackFunc>( 2756b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org GetProcAddress(mag_lib_handle_, "MagSetImageScalingCallback")); 2766b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 2776b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org if (!mag_initialize_func_ || !mag_uninitialize_func_ || 2786b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org !set_window_source_func_ || !set_window_filter_list_func_ || 2796b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org !set_image_scaling_callback_func_) { 2806b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org LOG_F(LS_WARNING) << "Failed to initialize ScreenCapturerWinMagnifier: " 2816b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org << "library functions missing."; 2826b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org return false; 2836b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org } 2846b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 2856b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org BOOL result = mag_initialize_func_(); 2866b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org if (!result) { 2876b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org LOG_F(LS_WARNING) << "Failed to initialize ScreenCapturerWinMagnifier: " 2886b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org << "error from MagInitialize " << GetLastError(); 2896b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org return false; 2906b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org } 2916b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 2926b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org HMODULE hInstance = NULL; 2936b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org result = GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | 2946b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, 2956b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org reinterpret_cast<char*>(&DefWindowProc), 2966b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org &hInstance); 2976b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org if (!result) { 2986b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org mag_uninitialize_func_(); 2996b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org LOG_F(LS_WARNING) << "Failed to initialize ScreenCapturerWinMagnifier: " 3006b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org << "error from GetModulehandleExA " << GetLastError(); 3016b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org return false; 3026b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org } 3036b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 3046b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org // Register the host window class. See the MSDN documentation of the 3056b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org // Magnification API for more infomation. 3066b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org WNDCLASSEX wcex = {}; 3076b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org wcex.cbSize = sizeof(WNDCLASSEX); 3086b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org wcex.lpfnWndProc = &DefWindowProc; 3096b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org wcex.hInstance = hInstance; 3106b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org wcex.hCursor = LoadCursor(NULL, IDC_ARROW); 3116b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org wcex.lpszClassName = kMagnifierHostClass; 3126b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 3136b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org // Ignore the error which may happen when the class is already registered. 3146b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org RegisterClassEx(&wcex); 3156b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 3166b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org // Create the host window. 3176b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org host_window_ = CreateWindowEx(WS_EX_LAYERED, 3186b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org kMagnifierHostClass, 3196b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org kHostWindowName, 3206b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 0, 3216b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 0, 0, 0, 0, 3226b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org NULL, 3236b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org NULL, 3246b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org hInstance, 3256b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org NULL); 3266b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org if (!host_window_) { 3276b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org mag_uninitialize_func_(); 3286b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org LOG_F(LS_WARNING) << "Failed to initialize ScreenCapturerWinMagnifier: " 3296b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org << "error from creating host window " << GetLastError(); 3306b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org return false; 3316b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org } 3326b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 3336b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org // Create the magnifier control. 3346b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org magnifier_window_ = CreateWindow(kMagnifierWindowClass, 3356b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org kMagnifierWindowName, 3366b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org WS_CHILD | WS_VISIBLE, 3376b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 0, 0, 0, 0, 3386b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org host_window_, 3396b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org NULL, 3406b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org hInstance, 3416b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org NULL); 3426b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org if (!magnifier_window_) { 3436b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org mag_uninitialize_func_(); 3446b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org LOG_F(LS_WARNING) << "Failed to initialize ScreenCapturerWinMagnifier: " 3456b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org << "error from creating magnifier window " 3466b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org << GetLastError(); 3476b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org return false; 3486b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org } 3496b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 3506b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org // Hide the host window. 3516b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org ShowWindow(host_window_, SW_HIDE); 3526b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 3536b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org // Set the scaling callback to receive captured image. 3546b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org result = set_image_scaling_callback_func_( 3556b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org magnifier_window_, 3566b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org &ScreenCapturerWinMagnifier::OnMagImageScalingCallback); 3576b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org if (!result) { 3586b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org mag_uninitialize_func_(); 3596b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org LOG_F(LS_WARNING) << "Failed to initialize ScreenCapturerWinMagnifier: " 3606b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org << "error from MagSetImageScalingCallback " 3616b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org << GetLastError(); 3626b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org return false; 3636b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org } 3646b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 3656b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org if (excluded_window_) { 3666b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org result = set_window_filter_list_func_( 3676b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org magnifier_window_, MW_FILTERMODE_EXCLUDE, 1, &excluded_window_); 3686b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org if (!result) { 3696b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org mag_uninitialize_func_(); 3706b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org LOG_F(LS_WARNING) << "Failed to initialize ScreenCapturerWinMagnifier: " 3716b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org << "error from MagSetWindowFilterList " 3726b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org << GetLastError(); 3736b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org return false; 3746b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org } 3756b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org } 3766b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 3776b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org if (tls_index_.Value() == TLS_OUT_OF_INDEXES) { 3786b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org // More than one threads may get here at the same time, but only one will 3796b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org // write to tls_index_ using CompareExchange. 3806b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org DWORD new_tls_index = TlsAlloc(); 3816b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org if (!tls_index_.CompareExchange(new_tls_index, TLS_OUT_OF_INDEXES)) 3826b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org TlsFree(new_tls_index); 3836b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org } 3846b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 3856b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org assert(tls_index_.Value() != TLS_OUT_OF_INDEXES); 3866b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org TlsSetValue(tls_index_.Value(), this); 3876b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 3886b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org magnifier_initialized_ = true; 3896b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org return true; 3906b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org} 3916b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 3926b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.orgvoid ScreenCapturerWinMagnifier::OnCaptured(void* data, 3936b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org const MAGIMAGEHEADER& header) { 3946b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org DesktopFrame* current_frame = queue_.current_frame(); 3956b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 3966b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org // Verify the format. 3976b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org // TODO(jiayl): support capturing sources with pixel formats other than RGBA. 3986b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org int captured_bytes_per_pixel = header.cbSize / header.width / header.height; 3996b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org if (header.format != GUID_WICPixelFormat32bppRGBA || 4006b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org header.width != static_cast<UINT>(current_frame->size().width()) || 4016b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org header.height != static_cast<UINT>(current_frame->size().height()) || 4026b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org header.stride != static_cast<UINT>(current_frame->stride()) || 4036b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org captured_bytes_per_pixel != DesktopFrame::kBytesPerPixel) { 4046b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org LOG_F(LS_WARNING) << "Output format does not match the captured format: " 4056b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org << "width = " << header.width << ", " 4066b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org << "height = " << header.height << ", " 4076b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org << "stride = " << header.stride << ", " 4086b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org << "bpp = " << captured_bytes_per_pixel << ", " 4096b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org << "pixel format RGBA ? " 4106b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org << (header.format == GUID_WICPixelFormat32bppRGBA) << "."; 4116b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org return; 4126b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org } 4136b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 4146b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org // Copy the data into the frame. 4156b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org current_frame->CopyPixelsFrom( 4166b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org reinterpret_cast<uint8_t*>(data), 4176b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org header.stride, 4186b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org DesktopRect::MakeXYWH(0, 0, header.width, header.height)); 4196b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 4206b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org magnifier_capture_succeeded_ = true; 4216b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org} 4226b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 4236b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.orgvoid ScreenCapturerWinMagnifier::CreateCurrentFrameIfNecessary( 4246b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org const DesktopSize& size) { 4256b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org // If the current buffer is from an older generation then allocate a new one. 4266b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org // Note that we can't reallocate other buffers at this point, since the caller 4276b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org // may still be reading from them. 4286b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org if (!queue_.current_frame() || !queue_.current_frame()->size().equals(size)) { 4296b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org size_t buffer_size = 4306b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org size.width() * size.height() * DesktopFrame::kBytesPerPixel; 4316b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org SharedMemory* shared_memory = callback_->CreateSharedMemory(buffer_size); 4326b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 4336b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org scoped_ptr<DesktopFrame> buffer; 4346b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org if (shared_memory) { 4356b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org buffer.reset(new SharedMemoryDesktopFrame( 4366b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org size, size.width() * DesktopFrame::kBytesPerPixel, shared_memory)); 4376b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org } else { 4386b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org buffer.reset(new BasicDesktopFrame(size)); 4396b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org } 4406b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org queue_.ReplaceCurrentFrame(buffer.release()); 4416b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org } 4426b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org} 4436b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 4446b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.orgbool ScreenCapturerWinMagnifier::IsCapturingPrimaryScreenOnly() const { 4456b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org if (current_screen_id_ != kFullDesktopScreenId) 4466b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org return current_screen_id_ == 0; // the primary screen is always '0'. 4476b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 4486b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org return GetSystemMetrics(SM_CMONITORS) == 1; 4496b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org} 4506b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 4516b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.orgvoid ScreenCapturerWinMagnifier::StartFallbackCapturer() { 4526b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org assert(fallback_capturer_); 4536b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org if (!fallback_capturer_started_) { 4546b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org fallback_capturer_started_ = true; 4556b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 4566b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org fallback_capturer_->Start(callback_); 4576b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org fallback_capturer_->SelectScreen(current_screen_id_); 4586b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org } 4596b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org} 4606b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org 4616b6e3eacfd0ba5d01fb391e72ff2bbf630f231e2jiayl@webrtc.org} // namespace webrtc 462