blob: 19202a75e97596ff9dfb4f2a2180478ffa38e80e [file] [log] [blame]
jiayl@webrtc.org42204342014-05-05 16:08:47 +00001/*
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
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#ifndef MODULES_DESKTOP_CAPTURE_WIN_SCREEN_CAPTURER_WIN_MAGNIFIER_H_
12#define MODULES_DESKTOP_CAPTURE_WIN_SCREEN_CAPTURER_WIN_MAGNIFIER_H_
jiayl@webrtc.org42204342014-05-05 16:08:47 +000013
14#include <magnification.h>
15#include <wincodec.h>
Yves Gerey665174f2018-06-19 15:03:05 +020016#include <windows.h>
jiayl@webrtc.org42204342014-05-05 16:08:47 +000017
Jonas Olssona4d87372019-07-05 19:08:33 +020018#include <memory>
19
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020020#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"
Steve Anton10542f22019-01-11 09:11:00 -080025#include "rtc_base/constructor_magic.h"
jiayl@webrtc.org42204342014-05-05 16:08:47 +000026
27namespace webrtc {
28
29class DesktopFrame;
30class DesktopRect;
jiayl@webrtc.org42204342014-05-05 16:08:47 +000031
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.
zijiehec59bf042016-09-23 17:54:32 -070036//
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.
zijiehe98903d22016-11-10 21:57:10 -080040class ScreenCapturerWinMagnifier : public DesktopCapturer {
jiayl@webrtc.org42204342014-05-05 16:08:47 +000041 public:
zijiehe3fa87f72017-02-22 13:47:00 -080042 ScreenCapturerWinMagnifier();
sergeyue1831212016-10-26 13:15:42 -070043 ~ScreenCapturerWinMagnifier() override;
jiayl@webrtc.org42204342014-05-05 16:08:47 +000044
45 // Overridden from ScreenCapturer:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +000046 void Start(Callback* callback) override;
sergeyucc9669c2016-02-09 15:13:26 -080047 void SetSharedMemoryFactory(
kwiberg84be5112016-04-27 01:19:58 -070048 std::unique_ptr<SharedMemoryFactory> shared_memory_factory) override;
zijiehe91902cb2016-10-13 16:47:49 -070049 void CaptureFrame() override;
zijiehefce49052016-11-07 15:25:18 -080050 bool GetSourceList(SourceList* screens) override;
51 bool SelectSource(SourceId id) override;
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +000052 void SetExcludedWindow(WindowId window) override;
jiayl@webrtc.org42204342014-05-05 16:08:47 +000053
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
sergeyu5d910282016-06-07 16:41:58 -0700101 Callback* callback_ = nullptr;
kwiberg2bb3afa2016-03-16 15:58:08 -0700102 std::unique_ptr<SharedMemoryFactory> shared_memory_factory_;
sergeyu5d910282016-06-07 16:41:58 -0700103 ScreenId current_screen_id_ = kFullDesktopScreenId;
jiayl@webrtc.org42204342014-05-05 16:08:47 +0000104 std::wstring current_device_key_;
sergeyu5d910282016-06-07 16:41:58 -0700105 HWND excluded_window_ = NULL;
jiayl@webrtc.org42204342014-05-05 16:08:47 +0000106
jiayl@webrtc.org42204342014-05-05 16:08:47 +0000107 // Queue of the frames buffers.
zijiehe809dcb42016-04-22 16:08:39 -0700108 ScreenCaptureFrameQueue<SharedDesktopFrame> queue_;
jiayl@webrtc.org42204342014-05-05 16:08:47 +0000109
jiayl@webrtc.org42204342014-05-05 16:08:47 +0000110 ScopedThreadDesktop desktop_;
111
112 // Used for getting the screen dpi.
sergeyu5d910282016-06-07 16:41:58 -0700113 HDC desktop_dc_ = NULL;
jiayl@webrtc.org42204342014-05-05 16:08:47 +0000114
sergeyu5d910282016-06-07 16:41:58 -0700115 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;
jiayl@webrtc.org42204342014-05-05 16:08:47 +0000121
122 // The hidden window hosting the magnifier control.
sergeyu5d910282016-06-07 16:41:58 -0700123 HWND host_window_ = NULL;
jiayl@webrtc.org42204342014-05-05 16:08:47 +0000124 // The magnifier control that captures the screen.
sergeyu5d910282016-06-07 16:41:58 -0700125 HWND magnifier_window_ = NULL;
jiayl@webrtc.org42204342014-05-05 16:08:47 +0000126
127 // True if the magnifier control has been successfully initialized.
sergeyu5d910282016-06-07 16:41:58 -0700128 bool magnifier_initialized_ = false;
jiayl@webrtc.org42204342014-05-05 16:08:47 +0000129
130 // True if the last OnMagImageScalingCallback was called and handled
131 // successfully. Reset at the beginning of each CaptureImage call.
sergeyu5d910282016-06-07 16:41:58 -0700132 bool magnifier_capture_succeeded_ = true;
jiayl@webrtc.org42204342014-05-05 16:08:47 +0000133
henrikg3c089d72015-09-16 05:37:44 -0700134 RTC_DISALLOW_COPY_AND_ASSIGN(ScreenCapturerWinMagnifier);
jiayl@webrtc.org42204342014-05-05 16:08:47 +0000135};
136
137} // namespace webrtc
138
Mirko Bonadei92ea95e2017-09-15 06:47:31 +0200139#endif // MODULES_DESKTOP_CAPTURE_WIN_SCREEN_CAPTURER_WIN_MAGNIFIER_H_