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