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 MODULES_DESKTOP_CAPTURE_WIN_SCREEN_CAPTURER_WIN_MAGNIFIER_H_ 12 #define MODULES_DESKTOP_CAPTURE_WIN_SCREEN_CAPTURER_WIN_MAGNIFIER_H_ 13 14 #include <magnification.h> 15 #include <wincodec.h> 16 #include <windows.h> 17 18 #include <memory> 19 20 #include "modules/desktop_capture/desktop_capturer.h" 21 #include "modules/desktop_capture/screen_capture_frame_queue.h" 22 #include "modules/desktop_capture/screen_capturer_helper.h" 23 #include "modules/desktop_capture/shared_desktop_frame.h" 24 #include "modules/desktop_capture/win/scoped_thread_desktop.h" 25 #include "rtc_base/constructor_magic.h" 26 27 namespace webrtc { 28 29 class DesktopFrame; 30 class DesktopRect; 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 // 37 // This class does not detect DesktopFrame::updated_region(), the field is 38 // always set to the entire frame rectangle. ScreenCapturerDifferWrapper should 39 // be used if that functionality is necessary. 40 class ScreenCapturerWinMagnifier : public DesktopCapturer { 41 public: 42 ScreenCapturerWinMagnifier(); 43 ~ScreenCapturerWinMagnifier() override; 44 45 // Overridden from ScreenCapturer: 46 void Start(Callback* callback) override; 47 void SetSharedMemoryFactory( 48 std::unique_ptr<SharedMemoryFactory> shared_memory_factory) override; 49 void CaptureFrame() override; 50 bool GetSourceList(SourceList* screens) override; 51 bool SelectSource(SourceId id) override; 52 void SetExcludedWindow(WindowId window) override; 53 54 private: 55 typedef BOOL(WINAPI* MagImageScalingCallback)(HWND hwnd, 56 void* srcdata, 57 MAGIMAGEHEADER srcheader, 58 void* destdata, 59 MAGIMAGEHEADER destheader, 60 RECT unclipped, 61 RECT clipped, 62 HRGN dirty); 63 typedef BOOL(WINAPI* MagInitializeFunc)(void); 64 typedef BOOL(WINAPI* MagUninitializeFunc)(void); 65 typedef BOOL(WINAPI* MagSetWindowSourceFunc)(HWND hwnd, RECT rect); 66 typedef BOOL(WINAPI* MagSetWindowFilterListFunc)(HWND hwnd, 67 DWORD dwFilterMode, 68 int count, 69 HWND* pHWND); 70 typedef BOOL(WINAPI* MagSetImageScalingCallbackFunc)( 71 HWND hwnd, 72 MagImageScalingCallback callback); 73 74 static BOOL WINAPI OnMagImageScalingCallback(HWND hwnd, 75 void* srcdata, 76 MAGIMAGEHEADER srcheader, 77 void* destdata, 78 MAGIMAGEHEADER destheader, 79 RECT unclipped, 80 RECT clipped, 81 HRGN dirty); 82 83 // Captures the screen within |rect| in the desktop coordinates. Returns true 84 // if succeeded. 85 // It can only capture the primary screen for now. The magnification library 86 // crashes under some screen configurations (e.g. secondary screen on top of 87 // primary screen) if it tries to capture a non-primary screen. The caller 88 // must make sure not calling it on non-primary screens. 89 bool CaptureImage(const DesktopRect& rect); 90 91 // Helper method for setting up the magnifier control. Returns true if 92 // succeeded. 93 bool InitializeMagnifier(); 94 95 // Called by OnMagImageScalingCallback to output captured data. 96 void OnCaptured(void* data, const MAGIMAGEHEADER& header); 97 98 // Makes sure the current frame exists and matches |size|. 99 void CreateCurrentFrameIfNecessary(const DesktopSize& size); 100 101 Callback* callback_ = nullptr; 102 std::unique_ptr<SharedMemoryFactory> shared_memory_factory_; 103 ScreenId current_screen_id_ = kFullDesktopScreenId; 104 std::wstring current_device_key_; 105 HWND excluded_window_ = NULL; 106 107 // Queue of the frames buffers. 108 ScreenCaptureFrameQueue<SharedDesktopFrame> queue_; 109 110 ScopedThreadDesktop desktop_; 111 112 // Used for getting the screen dpi. 113 HDC desktop_dc_ = NULL; 114 115 HMODULE mag_lib_handle_ = NULL; 116 MagInitializeFunc mag_initialize_func_ = nullptr; 117 MagUninitializeFunc mag_uninitialize_func_ = nullptr; 118 MagSetWindowSourceFunc set_window_source_func_ = nullptr; 119 MagSetWindowFilterListFunc set_window_filter_list_func_ = nullptr; 120 MagSetImageScalingCallbackFunc set_image_scaling_callback_func_ = nullptr; 121 122 // The hidden window hosting the magnifier control. 123 HWND host_window_ = NULL; 124 // The magnifier control that captures the screen. 125 HWND magnifier_window_ = NULL; 126 127 // True if the magnifier control has been successfully initialized. 128 bool magnifier_initialized_ = false; 129 130 // True if the last OnMagImageScalingCallback was called and handled 131 // successfully. Reset at the beginning of each CaptureImage call. 132 bool magnifier_capture_succeeded_ = true; 133 134 RTC_DISALLOW_COPY_AND_ASSIGN(ScreenCapturerWinMagnifier); 135 }; 136 137 } // namespace webrtc 138 139 #endif // MODULES_DESKTOP_CAPTURE_WIN_SCREEN_CAPTURER_WIN_MAGNIFIER_H_ 140