blob: b25633da0dba21b9ad19aba6778f98900c07e87d [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
kwiberg2bb3afa2016-03-16 15:58:08 -070014#include <memory>
15
henrike@webrtc.org88fbb2d2014-05-21 21:18:46 +000016#include <windows.h>
jiayl@webrtc.org42204342014-05-05 16:08:47 +000017#include <magnification.h>
18#include <wincodec.h>
jiayl@webrtc.org42204342014-05-05 16:08:47 +000019
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"
25#include "rtc_base/constructormagic.h"
26#include "system_wrappers/include/atomic32.h"
jiayl@webrtc.org42204342014-05-05 16:08:47 +000027
28namespace webrtc {
29
30class DesktopFrame;
31class DesktopRect;
jiayl@webrtc.org42204342014-05-05 16:08:47 +000032
33// Captures the screen using the Magnification API to support window exclusion.
34// Each capturer must run on a dedicated thread because it uses thread local
35// storage for redirecting the library callback. Also the thread must have a UI
36// message loop to handle the window messages for the magnifier window.
zijiehec59bf042016-09-23 17:54:32 -070037//
38// This class does not detect DesktopFrame::updated_region(), the field is
39// always set to the entire frame rectangle. ScreenCapturerDifferWrapper should
40// be used if that functionality is necessary.
zijiehe98903d22016-11-10 21:57:10 -080041class ScreenCapturerWinMagnifier : public DesktopCapturer {
jiayl@webrtc.org42204342014-05-05 16:08:47 +000042 public:
zijiehe3fa87f72017-02-22 13:47:00 -080043 ScreenCapturerWinMagnifier();
sergeyue1831212016-10-26 13:15:42 -070044 ~ScreenCapturerWinMagnifier() override;
jiayl@webrtc.org42204342014-05-05 16:08:47 +000045
46 // Overridden from ScreenCapturer:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +000047 void Start(Callback* callback) override;
sergeyucc9669c2016-02-09 15:13:26 -080048 void SetSharedMemoryFactory(
kwiberg84be5112016-04-27 01:19:58 -070049 std::unique_ptr<SharedMemoryFactory> shared_memory_factory) override;
zijiehe91902cb2016-10-13 16:47:49 -070050 void CaptureFrame() override;
zijiehefce49052016-11-07 15:25:18 -080051 bool GetSourceList(SourceList* screens) override;
52 bool SelectSource(SourceId id) override;
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +000053 void SetExcludedWindow(WindowId window) override;
jiayl@webrtc.org42204342014-05-05 16:08:47 +000054
55 private:
56 typedef BOOL(WINAPI* MagImageScalingCallback)(HWND hwnd,
57 void* srcdata,
58 MAGIMAGEHEADER srcheader,
59 void* destdata,
60 MAGIMAGEHEADER destheader,
61 RECT unclipped,
62 RECT clipped,
63 HRGN dirty);
64 typedef BOOL(WINAPI* MagInitializeFunc)(void);
65 typedef BOOL(WINAPI* MagUninitializeFunc)(void);
66 typedef BOOL(WINAPI* MagSetWindowSourceFunc)(HWND hwnd, RECT rect);
67 typedef BOOL(WINAPI* MagSetWindowFilterListFunc)(HWND hwnd,
68 DWORD dwFilterMode,
69 int count,
70 HWND* pHWND);
71 typedef BOOL(WINAPI* MagSetImageScalingCallbackFunc)(
72 HWND hwnd,
73 MagImageScalingCallback callback);
74
75 static BOOL WINAPI OnMagImageScalingCallback(HWND hwnd,
76 void* srcdata,
77 MAGIMAGEHEADER srcheader,
78 void* destdata,
79 MAGIMAGEHEADER destheader,
80 RECT unclipped,
81 RECT clipped,
82 HRGN dirty);
83
84 // Captures the screen within |rect| in the desktop coordinates. Returns true
85 // if succeeded.
86 // It can only capture the primary screen for now. The magnification library
87 // crashes under some screen configurations (e.g. secondary screen on top of
88 // primary screen) if it tries to capture a non-primary screen. The caller
89 // must make sure not calling it on non-primary screens.
90 bool CaptureImage(const DesktopRect& rect);
91
92 // Helper method for setting up the magnifier control. Returns true if
93 // succeeded.
94 bool InitializeMagnifier();
95
96 // Called by OnMagImageScalingCallback to output captured data.
97 void OnCaptured(void* data, const MAGIMAGEHEADER& header);
98
99 // Makes sure the current frame exists and matches |size|.
100 void CreateCurrentFrameIfNecessary(const DesktopSize& size);
101
jiayl@webrtc.org42204342014-05-05 16:08:47 +0000102 static Atomic32 tls_index_;
103
sergeyu5d910282016-06-07 16:41:58 -0700104 Callback* callback_ = nullptr;
kwiberg2bb3afa2016-03-16 15:58:08 -0700105 std::unique_ptr<SharedMemoryFactory> shared_memory_factory_;
sergeyu5d910282016-06-07 16:41:58 -0700106 ScreenId current_screen_id_ = kFullDesktopScreenId;
jiayl@webrtc.org42204342014-05-05 16:08:47 +0000107 std::wstring current_device_key_;
sergeyu5d910282016-06-07 16:41:58 -0700108 HWND excluded_window_ = NULL;
jiayl@webrtc.org42204342014-05-05 16:08:47 +0000109
jiayl@webrtc.org42204342014-05-05 16:08:47 +0000110 // Queue of the frames buffers.
zijiehe809dcb42016-04-22 16:08:39 -0700111 ScreenCaptureFrameQueue<SharedDesktopFrame> queue_;
jiayl@webrtc.org42204342014-05-05 16:08:47 +0000112
jiayl@webrtc.org42204342014-05-05 16:08:47 +0000113 ScopedThreadDesktop desktop_;
114
115 // Used for getting the screen dpi.
sergeyu5d910282016-06-07 16:41:58 -0700116 HDC desktop_dc_ = NULL;
jiayl@webrtc.org42204342014-05-05 16:08:47 +0000117
sergeyu5d910282016-06-07 16:41:58 -0700118 HMODULE mag_lib_handle_ = NULL;
119 MagInitializeFunc mag_initialize_func_ = nullptr;
120 MagUninitializeFunc mag_uninitialize_func_ = nullptr;
121 MagSetWindowSourceFunc set_window_source_func_ = nullptr;
122 MagSetWindowFilterListFunc set_window_filter_list_func_ = nullptr;
123 MagSetImageScalingCallbackFunc set_image_scaling_callback_func_ = nullptr;
jiayl@webrtc.org42204342014-05-05 16:08:47 +0000124
125 // The hidden window hosting the magnifier control.
sergeyu5d910282016-06-07 16:41:58 -0700126 HWND host_window_ = NULL;
jiayl@webrtc.org42204342014-05-05 16:08:47 +0000127 // The magnifier control that captures the screen.
sergeyu5d910282016-06-07 16:41:58 -0700128 HWND magnifier_window_ = NULL;
jiayl@webrtc.org42204342014-05-05 16:08:47 +0000129
130 // True if the magnifier control has been successfully initialized.
sergeyu5d910282016-06-07 16:41:58 -0700131 bool magnifier_initialized_ = false;
jiayl@webrtc.org42204342014-05-05 16:08:47 +0000132
133 // True if the last OnMagImageScalingCallback was called and handled
134 // successfully. Reset at the beginning of each CaptureImage call.
sergeyu5d910282016-06-07 16:41:58 -0700135 bool magnifier_capture_succeeded_ = true;
jiayl@webrtc.org42204342014-05-05 16:08:47 +0000136
henrikg3c089d72015-09-16 05:37:44 -0700137 RTC_DISALLOW_COPY_AND_ASSIGN(ScreenCapturerWinMagnifier);
jiayl@webrtc.org42204342014-05-05 16:08:47 +0000138};
139
140} // namespace webrtc
141
Mirko Bonadei92ea95e2017-09-15 06:47:31 +0200142#endif // MODULES_DESKTOP_CAPTURE_WIN_SCREEN_CAPTURER_WIN_MAGNIFIER_H_