1 /* 2 * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 #ifndef WEBRTC_MODULES_DESKTOP_CAPTURE_WIN_SCREEN_CAPTURER_WIN_MAGNIFIER_H_ 12 #define WEBRTC_MODULES_DESKTOP_CAPTURE_WIN_SCREEN_CAPTURER_WIN_MAGNIFIER_H_ 13 14 #include <windows.h> 15 #include <magnification.h> 16 #include <wincodec.h> 17 18 #include "webrtc/base/constructormagic.h" 19 #include "webrtc/base/scoped_ptr.h" 20 #include "webrtc/modules/desktop_capture/screen_capture_frame_queue.h" 21 #include "webrtc/modules/desktop_capture/screen_capturer.h" 22 #include "webrtc/modules/desktop_capture/screen_capturer_helper.h" 23 #include "webrtc/modules/desktop_capture/win/scoped_thread_desktop.h" 24 #include "webrtc/system_wrappers/include/atomic32.h" 25 26 namespace webrtc { 27 28 class DesktopFrame; 29 class DesktopRect; 30 class Differ; 31 32 // Captures the screen using the Magnification API to support window exclusion. 33 // Each capturer must run on a dedicated thread because it uses thread local 34 // storage for redirecting the library callback. Also the thread must have a UI 35 // message loop to handle the window messages for the magnifier window. 36 class ScreenCapturerWinMagnifier : public ScreenCapturer { 37 public: 38 // |fallback_capturer| will be used to capture the screen if a non-primary 39 // screen is being captured, or the OS does not support Magnification API, or 40 // the magnifier capturer fails (e.g. in Windows8 Metro mode). 41 explicit ScreenCapturerWinMagnifier( 42 rtc::scoped_ptr<ScreenCapturer> fallback_capturer); 43 virtual ~ScreenCapturerWinMagnifier(); 44 45 // Overridden from ScreenCapturer: 46 void Start(Callback* callback) override; 47 void Capture(const DesktopRegion& region) override; 48 bool GetScreenList(ScreenList* screens) override; 49 bool SelectScreen(ScreenId id) override; 50 void SetExcludedWindow(WindowId window) override; 51 52 private: 53 typedef BOOL(WINAPI* MagImageScalingCallback)(HWND hwnd, 54 void* srcdata, 55 MAGIMAGEHEADER srcheader, 56 void* destdata, 57 MAGIMAGEHEADER destheader, 58 RECT unclipped, 59 RECT clipped, 60 HRGN dirty); 61 typedef BOOL(WINAPI* MagInitializeFunc)(void); 62 typedef BOOL(WINAPI* MagUninitializeFunc)(void); 63 typedef BOOL(WINAPI* MagSetWindowSourceFunc)(HWND hwnd, RECT rect); 64 typedef BOOL(WINAPI* MagSetWindowFilterListFunc)(HWND hwnd, 65 DWORD dwFilterMode, 66 int count, 67 HWND* pHWND); 68 typedef BOOL(WINAPI* MagSetImageScalingCallbackFunc)( 69 HWND hwnd, 70 MagImageScalingCallback callback); 71 72 static BOOL WINAPI OnMagImageScalingCallback(HWND hwnd, 73 void* srcdata, 74 MAGIMAGEHEADER srcheader, 75 void* destdata, 76 MAGIMAGEHEADER destheader, 77 RECT unclipped, 78 RECT clipped, 79 HRGN dirty); 80 81 // Captures the screen within |rect| in the desktop coordinates. Returns true 82 // if succeeded. 83 // It can only capture the primary screen for now. The magnification library 84 // crashes under some screen configurations (e.g. secondary screen on top of 85 // primary screen) if it tries to capture a non-primary screen. The caller 86 // must make sure not calling it on non-primary screens. 87 bool CaptureImage(const DesktopRect& rect); 88 89 // Helper method for setting up the magnifier control. Returns true if 90 // succeeded. 91 bool InitializeMagnifier(); 92 93 // Called by OnMagImageScalingCallback to output captured data. 94 void OnCaptured(void* data, const MAGIMAGEHEADER& header); 95 96 // Makes sure the current frame exists and matches |size|. 97 void CreateCurrentFrameIfNecessary(const DesktopSize& size); 98 99 // Start the fallback capturer and select the screen. 100 void StartFallbackCapturer(); 101 102 static Atomic32 tls_index_; 103 104 rtc::scoped_ptr<ScreenCapturer> fallback_capturer_; 105 bool fallback_capturer_started_; 106 Callback* callback_; 107 ScreenId current_screen_id_; 108 std::wstring current_device_key_; 109 HWND excluded_window_; 110 111 // A thread-safe list of invalid rectangles, and the size of the most 112 // recently captured screen. 113 ScreenCapturerHelper helper_; 114 115 // Queue of the frames buffers. 116 ScreenCaptureFrameQueue queue_; 117 118 // Class to calculate the difference between two screen bitmaps. 119 rtc::scoped_ptr<Differ> differ_; 120 121 // Used to suppress duplicate logging of SetThreadExecutionState errors. 122 bool set_thread_execution_state_failed_; 123 124 ScopedThreadDesktop desktop_; 125 126 // Used for getting the screen dpi. 127 HDC desktop_dc_; 128 129 HMODULE mag_lib_handle_; 130 MagInitializeFunc mag_initialize_func_; 131 MagUninitializeFunc mag_uninitialize_func_; 132 MagSetWindowSourceFunc set_window_source_func_; 133 MagSetWindowFilterListFunc set_window_filter_list_func_; 134 MagSetImageScalingCallbackFunc set_image_scaling_callback_func_; 135 136 // The hidden window hosting the magnifier control. 137 HWND host_window_; 138 // The magnifier control that captures the screen. 139 HWND magnifier_window_; 140 141 // True if the magnifier control has been successfully initialized. 142 bool magnifier_initialized_; 143 144 // True if the last OnMagImageScalingCallback was called and handled 145 // successfully. Reset at the beginning of each CaptureImage call. 146 bool magnifier_capture_succeeded_; 147 148 RTC_DISALLOW_COPY_AND_ASSIGN(ScreenCapturerWinMagnifier); 149 }; 150 151 } // namespace webrtc 152 153 #endif // WEBRTC_MODULES_DESKTOP_CAPTURE_WIN_SCREEN_CAPTURER_WIN_MAGNIFIER_H_ 154