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 WEBRTC_MODULES_DESKTOP_CAPTURE_WIN_SCREEN_CAPTURER_WIN_MAGNIFIER_H_ 12#define WEBRTC_MODULES_DESKTOP_CAPTURE_WIN_SCREEN_CAPTURER_WIN_MAGNIFIER_H_ 13 14#include <windows.h> 15#include <magnification.h> 16#include <wincodec.h> 17 18#include "webrtc/base/constructormagic.h" 19#include "webrtc/modules/desktop_capture/screen_capture_frame_queue.h" 20#include "webrtc/modules/desktop_capture/screen_capturer.h" 21#include "webrtc/modules/desktop_capture/screen_capturer_helper.h" 22#include "webrtc/modules/desktop_capture/win/scoped_thread_desktop.h" 23#include "webrtc/system_wrappers/interface/atomic32.h" 24#include "webrtc/system_wrappers/interface/scoped_ptr.h" 25 26namespace webrtc { 27 28class DesktopFrame; 29class DesktopRect; 30class Differ; 31class MouseShapeObserver; 32 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. 37class ScreenCapturerWinMagnifier : public ScreenCapturer { 38 public: 39 // |fallback_capturer| will be used to capture the screen if a non-primary 40 // screen is being captured, or the OS does not support Magnification API, or 41 // the magnifier capturer fails (e.g. in Windows8 Metro mode). 42 explicit ScreenCapturerWinMagnifier( 43 scoped_ptr<ScreenCapturer> fallback_capturer); 44 virtual ~ScreenCapturerWinMagnifier(); 45 46 // Overridden from ScreenCapturer: 47 virtual void Start(Callback* callback) OVERRIDE; 48 virtual void Capture(const DesktopRegion& region) OVERRIDE; 49 virtual void SetMouseShapeObserver( 50 MouseShapeObserver* mouse_shape_observer) OVERRIDE; 51 virtual bool GetScreenList(ScreenList* screens) OVERRIDE; 52 virtual bool SelectScreen(ScreenId id) OVERRIDE; 53 virtual void SetExcludedWindow(WindowId window) OVERRIDE; 54 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 102 // Returns true if we are capturing the primary screen only. 103 bool IsCapturingPrimaryScreenOnly() const; 104 105 // Start the fallback capturer and select the screen. 106 void StartFallbackCapturer(); 107 108 static Atomic32 tls_index_; 109 110 scoped_ptr<ScreenCapturer> fallback_capturer_; 111 bool fallback_capturer_started_; 112 Callback* callback_; 113 ScreenId current_screen_id_; 114 std::wstring current_device_key_; 115 HWND excluded_window_; 116 117 // A thread-safe list of invalid rectangles, and the size of the most 118 // recently captured screen. 119 ScreenCapturerHelper helper_; 120 121 // Queue of the frames buffers. 122 ScreenCaptureFrameQueue queue_; 123 124 // Class to calculate the difference between two screen bitmaps. 125 scoped_ptr<Differ> differ_; 126 127 // Used to suppress duplicate logging of SetThreadExecutionState errors. 128 bool set_thread_execution_state_failed_; 129 130 ScopedThreadDesktop desktop_; 131 132 // Used for getting the screen dpi. 133 HDC desktop_dc_; 134 135 HMODULE mag_lib_handle_; 136 MagInitializeFunc mag_initialize_func_; 137 MagUninitializeFunc mag_uninitialize_func_; 138 MagSetWindowSourceFunc set_window_source_func_; 139 MagSetWindowFilterListFunc set_window_filter_list_func_; 140 MagSetImageScalingCallbackFunc set_image_scaling_callback_func_; 141 142 // The hidden window hosting the magnifier control. 143 HWND host_window_; 144 // The magnifier control that captures the screen. 145 HWND magnifier_window_; 146 147 // True if the magnifier control has been successfully initialized. 148 bool magnifier_initialized_; 149 150 // True if the last OnMagImageScalingCallback was called and handled 151 // successfully. Reset at the beginning of each CaptureImage call. 152 bool magnifier_capture_succeeded_; 153 154 DISALLOW_COPY_AND_ASSIGN(ScreenCapturerWinMagnifier); 155}; 156 157} // namespace webrtc 158 159#endif // WEBRTC_MODULES_DESKTOP_CAPTURE_WIN_SCREEN_CAPTURER_WIN_MAGNIFIER_H_ 160