blob: 0978d8838f478b1961f6fd6c422619c6051e1c7e [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
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
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
henrike@webrtc.org88fbb2d2014-05-21 21:18:46 +000020#include "webrtc/base/constructormagic.h"
jiayl@webrtc.org42204342014-05-05 16:08:47 +000021#include "webrtc/modules/desktop_capture/screen_capture_frame_queue.h"
mcasas@webrtc.org2fa7f792014-05-21 11:07:29 +000022#include "webrtc/modules/desktop_capture/screen_capturer.h"
henrike@webrtc.org88fbb2d2014-05-21 21:18:46 +000023#include "webrtc/modules/desktop_capture/screen_capturer_helper.h"
zijiehe809dcb42016-04-22 16:08:39 -070024#include "webrtc/modules/desktop_capture/shared_desktop_frame.h"
jiayl@webrtc.org42204342014-05-05 16:08:47 +000025#include "webrtc/modules/desktop_capture/win/scoped_thread_desktop.h"
Henrik Kjellander98f53512015-10-28 18:17:40 +010026#include "webrtc/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.
jiayl@webrtc.org42204342014-05-05 16:08:47 +000041class ScreenCapturerWinMagnifier : public ScreenCapturer {
42 public:
43 // |fallback_capturer| will be used to capture the screen if a non-primary
44 // screen is being captured, or the OS does not support Magnification API, or
45 // the magnifier capturer fails (e.g. in Windows8 Metro mode).
46 explicit ScreenCapturerWinMagnifier(
zijiehe54fd5792016-11-02 14:49:35 -070047 std::unique_ptr<DesktopCapturer> fallback_capturer);
sergeyue1831212016-10-26 13:15:42 -070048 ~ScreenCapturerWinMagnifier() override;
jiayl@webrtc.org42204342014-05-05 16:08:47 +000049
50 // Overridden from ScreenCapturer:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +000051 void Start(Callback* callback) override;
sergeyucc9669c2016-02-09 15:13:26 -080052 void SetSharedMemoryFactory(
kwiberg84be5112016-04-27 01:19:58 -070053 std::unique_ptr<SharedMemoryFactory> shared_memory_factory) override;
zijiehe91902cb2016-10-13 16:47:49 -070054 void CaptureFrame() override;
zijiehefce49052016-11-07 15:25:18 -080055 bool GetSourceList(SourceList* screens) override;
56 bool SelectSource(SourceId id) override;
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +000057 void SetExcludedWindow(WindowId window) override;
jiayl@webrtc.org42204342014-05-05 16:08:47 +000058
59 private:
60 typedef BOOL(WINAPI* MagImageScalingCallback)(HWND hwnd,
61 void* srcdata,
62 MAGIMAGEHEADER srcheader,
63 void* destdata,
64 MAGIMAGEHEADER destheader,
65 RECT unclipped,
66 RECT clipped,
67 HRGN dirty);
68 typedef BOOL(WINAPI* MagInitializeFunc)(void);
69 typedef BOOL(WINAPI* MagUninitializeFunc)(void);
70 typedef BOOL(WINAPI* MagSetWindowSourceFunc)(HWND hwnd, RECT rect);
71 typedef BOOL(WINAPI* MagSetWindowFilterListFunc)(HWND hwnd,
72 DWORD dwFilterMode,
73 int count,
74 HWND* pHWND);
75 typedef BOOL(WINAPI* MagSetImageScalingCallbackFunc)(
76 HWND hwnd,
77 MagImageScalingCallback callback);
78
79 static BOOL WINAPI OnMagImageScalingCallback(HWND hwnd,
80 void* srcdata,
81 MAGIMAGEHEADER srcheader,
82 void* destdata,
83 MAGIMAGEHEADER destheader,
84 RECT unclipped,
85 RECT clipped,
86 HRGN dirty);
87
88 // Captures the screen within |rect| in the desktop coordinates. Returns true
89 // if succeeded.
90 // It can only capture the primary screen for now. The magnification library
91 // crashes under some screen configurations (e.g. secondary screen on top of
92 // primary screen) if it tries to capture a non-primary screen. The caller
93 // must make sure not calling it on non-primary screens.
94 bool CaptureImage(const DesktopRect& rect);
95
96 // Helper method for setting up the magnifier control. Returns true if
97 // succeeded.
98 bool InitializeMagnifier();
99
100 // Called by OnMagImageScalingCallback to output captured data.
101 void OnCaptured(void* data, const MAGIMAGEHEADER& header);
102
103 // Makes sure the current frame exists and matches |size|.
104 void CreateCurrentFrameIfNecessary(const DesktopSize& size);
105
jiayl@webrtc.org42204342014-05-05 16:08:47 +0000106 // Start the fallback capturer and select the screen.
107 void StartFallbackCapturer();
108
109 static Atomic32 tls_index_;
110
zijiehe54fd5792016-11-02 14:49:35 -0700111 std::unique_ptr<DesktopCapturer> fallback_capturer_;
sergeyu5d910282016-06-07 16:41:58 -0700112 bool fallback_capturer_started_ = false;
113 Callback* callback_ = nullptr;
kwiberg2bb3afa2016-03-16 15:58:08 -0700114 std::unique_ptr<SharedMemoryFactory> shared_memory_factory_;
sergeyu5d910282016-06-07 16:41:58 -0700115 ScreenId current_screen_id_ = kFullDesktopScreenId;
jiayl@webrtc.org42204342014-05-05 16:08:47 +0000116 std::wstring current_device_key_;
sergeyu5d910282016-06-07 16:41:58 -0700117 HWND excluded_window_ = NULL;
jiayl@webrtc.org42204342014-05-05 16:08:47 +0000118
jiayl@webrtc.org42204342014-05-05 16:08:47 +0000119 // Queue of the frames buffers.
zijiehe809dcb42016-04-22 16:08:39 -0700120 ScreenCaptureFrameQueue<SharedDesktopFrame> queue_;
jiayl@webrtc.org42204342014-05-05 16:08:47 +0000121
jiayl@webrtc.org42204342014-05-05 16:08:47 +0000122 ScopedThreadDesktop desktop_;
123
124 // Used for getting the screen dpi.
sergeyu5d910282016-06-07 16:41:58 -0700125 HDC desktop_dc_ = NULL;
jiayl@webrtc.org42204342014-05-05 16:08:47 +0000126
sergeyu5d910282016-06-07 16:41:58 -0700127 HMODULE mag_lib_handle_ = NULL;
128 MagInitializeFunc mag_initialize_func_ = nullptr;
129 MagUninitializeFunc mag_uninitialize_func_ = nullptr;
130 MagSetWindowSourceFunc set_window_source_func_ = nullptr;
131 MagSetWindowFilterListFunc set_window_filter_list_func_ = nullptr;
132 MagSetImageScalingCallbackFunc set_image_scaling_callback_func_ = nullptr;
jiayl@webrtc.org42204342014-05-05 16:08:47 +0000133
134 // The hidden window hosting the magnifier control.
sergeyu5d910282016-06-07 16:41:58 -0700135 HWND host_window_ = NULL;
jiayl@webrtc.org42204342014-05-05 16:08:47 +0000136 // The magnifier control that captures the screen.
sergeyu5d910282016-06-07 16:41:58 -0700137 HWND magnifier_window_ = NULL;
jiayl@webrtc.org42204342014-05-05 16:08:47 +0000138
139 // True if the magnifier control has been successfully initialized.
sergeyu5d910282016-06-07 16:41:58 -0700140 bool magnifier_initialized_ = false;
jiayl@webrtc.org42204342014-05-05 16:08:47 +0000141
142 // True if the last OnMagImageScalingCallback was called and handled
143 // successfully. Reset at the beginning of each CaptureImage call.
sergeyu5d910282016-06-07 16:41:58 -0700144 bool magnifier_capture_succeeded_ = true;
jiayl@webrtc.org42204342014-05-05 16:08:47 +0000145
henrikg3c089d72015-09-16 05:37:44 -0700146 RTC_DISALLOW_COPY_AND_ASSIGN(ScreenCapturerWinMagnifier);
jiayl@webrtc.org42204342014-05-05 16:08:47 +0000147};
148
149} // namespace webrtc
150
151#endif // WEBRTC_MODULES_DESKTOP_CAPTURE_WIN_SCREEN_CAPTURER_WIN_MAGNIFIER_H_