Update WgcScreenSource* to use device indices instead of HMONITORs.
To maintain interoperability between different capturer implementations this change updates WgcScreenSourceEnumerator to return a list of device indices instead of a list of HMONITORs, and WgcScreenSource to accept a device index as the input SourceId. WGC still requires an HMONITOR to create the capture item, so this change also adds a utility function GetHmonitorFromDeviceIndex to convert them, as well as new tests to cover these changes. Bug: webrtc:12663 Change-Id: Ic29faa0f023ebc26b4276cf29ef3d15d976e8615 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/214600 Commit-Queue: Austin Orion <auorion@microsoft.com> Reviewed-by: Jamie Walch <jamiewalch@chromium.org> Cr-Commit-Position: refs/heads/master@{#33673}
This commit is contained in:
@ -16,48 +16,13 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "modules/desktop_capture/desktop_capturer.h"
|
#include "modules/desktop_capture/desktop_capturer.h"
|
||||||
|
#include "modules/desktop_capture/desktop_geometry.h"
|
||||||
#include "rtc_base/checks.h"
|
#include "rtc_base/checks.h"
|
||||||
|
#include "rtc_base/logging.h"
|
||||||
#include "rtc_base/string_utils.h"
|
#include "rtc_base/string_utils.h"
|
||||||
#include "rtc_base/win32.h"
|
#include "rtc_base/win32.h"
|
||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
namespace {
|
|
||||||
|
|
||||||
BOOL CALLBACK GetMonitorListHandler(HMONITOR monitor,
|
|
||||||
HDC hdc,
|
|
||||||
LPRECT rect,
|
|
||||||
LPARAM data) {
|
|
||||||
auto monitor_list = reinterpret_cast<DesktopCapturer::SourceList*>(data);
|
|
||||||
|
|
||||||
// Get the name of the monitor.
|
|
||||||
MONITORINFOEXA monitor_info;
|
|
||||||
monitor_info.cbSize = sizeof(MONITORINFOEXA);
|
|
||||||
if (!GetMonitorInfoA(monitor, &monitor_info)) {
|
|
||||||
// Continue the enumeration, but don't add this monitor to |monitor_list|.
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
DesktopCapturer::Source monitor_source;
|
|
||||||
monitor_source.id = reinterpret_cast<intptr_t>(monitor);
|
|
||||||
monitor_source.title = monitor_info.szDevice;
|
|
||||||
monitor_list->push_back(monitor_source);
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
// |monitors| is populated with HMONITOR values for each display monitor found.
|
|
||||||
// This is in contrast to |GetScreenList| which returns the display indices.
|
|
||||||
bool GetMonitorList(DesktopCapturer::SourceList* monitors) {
|
|
||||||
RTC_DCHECK_EQ(monitors->size(), 0U);
|
|
||||||
// |EnumDisplayMonitors| accepts a display context and a rectangle, which
|
|
||||||
// allows us to specify a certain region and return only the monitors that
|
|
||||||
// intersect that region. We, however, want all the monitors, so we pass in
|
|
||||||
// NULL parameters.
|
|
||||||
return EnumDisplayMonitors(/*hdc=*/NULL, /*clip_rect=*/NULL,
|
|
||||||
GetMonitorListHandler,
|
|
||||||
reinterpret_cast<LPARAM>(monitors));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool GetScreenList(DesktopCapturer::SourceList* screens,
|
bool GetScreenList(DesktopCapturer::SourceList* screens,
|
||||||
std::vector<std::string>* device_names /* = nullptr */) {
|
std::vector<std::string>* device_names /* = nullptr */) {
|
||||||
@ -73,12 +38,14 @@ bool GetScreenList(DesktopCapturer::SourceList* screens,
|
|||||||
enum_result = EnumDisplayDevicesW(NULL, device_index, &device, 0);
|
enum_result = EnumDisplayDevicesW(NULL, device_index, &device, 0);
|
||||||
|
|
||||||
// |enum_result| is 0 if we have enumerated all devices.
|
// |enum_result| is 0 if we have enumerated all devices.
|
||||||
if (!enum_result)
|
if (!enum_result) {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
// We only care about active displays.
|
// We only care about active displays.
|
||||||
if (!(device.StateFlags & DISPLAY_DEVICE_ACTIVE))
|
if (!(device.StateFlags & DISPLAY_DEVICE_ACTIVE)) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
screens->push_back({device_index, std::string()});
|
screens->push_back({device_index, std::string()});
|
||||||
if (device_names) {
|
if (device_names) {
|
||||||
@ -88,13 +55,52 @@ bool GetScreenList(DesktopCapturer::SourceList* screens,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsMonitorValid(DesktopCapturer::SourceId monitor) {
|
bool GetHmonitorFromDeviceIndex(const DesktopCapturer::SourceId device_index,
|
||||||
MONITORINFO monitor_info;
|
HMONITOR* hmonitor) {
|
||||||
monitor_info.cbSize = sizeof(MONITORINFO);
|
// A device index of |kFullDesktopScreenId| or -1 represents all screens, an
|
||||||
return GetMonitorInfoA(reinterpret_cast<HMONITOR>(monitor), &monitor_info);
|
// HMONITOR of 0 indicates the same.
|
||||||
|
if (device_index == kFullDesktopScreenId) {
|
||||||
|
*hmonitor = 0;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::wstring device_key;
|
||||||
|
if (!IsScreenValid(device_index, &device_key)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
DesktopRect screen_rect = GetScreenRect(device_index, device_key);
|
||||||
|
if (screen_rect.is_empty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
RECT rect = {screen_rect.left(), screen_rect.top(), screen_rect.right(),
|
||||||
|
screen_rect.bottom()};
|
||||||
|
|
||||||
|
HMONITOR monitor = MonitorFromRect(&rect, MONITOR_DEFAULTTONULL);
|
||||||
|
if (monitor == NULL) {
|
||||||
|
RTC_LOG(LS_WARNING) << "No HMONITOR found for supplied device index.";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
*hmonitor = monitor;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsScreenValid(DesktopCapturer::SourceId screen, std::wstring* device_key) {
|
bool IsMonitorValid(const HMONITOR monitor) {
|
||||||
|
// An HMONITOR of 0 refers to a virtual monitor that spans all physical
|
||||||
|
// monitors.
|
||||||
|
if (monitor == 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
MONITORINFO monitor_info;
|
||||||
|
monitor_info.cbSize = sizeof(MONITORINFO);
|
||||||
|
return GetMonitorInfoA(monitor, &monitor_info);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsScreenValid(const DesktopCapturer::SourceId screen,
|
||||||
|
std::wstring* device_key) {
|
||||||
if (screen == kFullDesktopScreenId) {
|
if (screen == kFullDesktopScreenId) {
|
||||||
*device_key = L"";
|
*device_key = L"";
|
||||||
return true;
|
return true;
|
||||||
@ -103,8 +109,9 @@ bool IsScreenValid(DesktopCapturer::SourceId screen, std::wstring* device_key) {
|
|||||||
DISPLAY_DEVICEW device;
|
DISPLAY_DEVICEW device;
|
||||||
device.cb = sizeof(device);
|
device.cb = sizeof(device);
|
||||||
BOOL enum_result = EnumDisplayDevicesW(NULL, screen, &device, 0);
|
BOOL enum_result = EnumDisplayDevicesW(NULL, screen, &device, 0);
|
||||||
if (enum_result)
|
if (enum_result) {
|
||||||
*device_key = device.DeviceKey;
|
*device_key = device.DeviceKey;
|
||||||
|
}
|
||||||
|
|
||||||
return !!enum_result;
|
return !!enum_result;
|
||||||
}
|
}
|
||||||
@ -116,7 +123,7 @@ DesktopRect GetFullscreenRect() {
|
|||||||
GetSystemMetrics(SM_CYVIRTUALSCREEN));
|
GetSystemMetrics(SM_CYVIRTUALSCREEN));
|
||||||
}
|
}
|
||||||
|
|
||||||
DesktopRect GetScreenRect(DesktopCapturer::SourceId screen,
|
DesktopRect GetScreenRect(const DesktopCapturer::SourceId screen,
|
||||||
const std::wstring& device_key) {
|
const std::wstring& device_key) {
|
||||||
if (screen == kFullDesktopScreenId) {
|
if (screen == kFullDesktopScreenId) {
|
||||||
return GetFullscreenRect();
|
return GetFullscreenRect();
|
||||||
@ -125,23 +132,26 @@ DesktopRect GetScreenRect(DesktopCapturer::SourceId screen,
|
|||||||
DISPLAY_DEVICEW device;
|
DISPLAY_DEVICEW device;
|
||||||
device.cb = sizeof(device);
|
device.cb = sizeof(device);
|
||||||
BOOL result = EnumDisplayDevicesW(NULL, screen, &device, 0);
|
BOOL result = EnumDisplayDevicesW(NULL, screen, &device, 0);
|
||||||
if (!result)
|
if (!result) {
|
||||||
return DesktopRect();
|
return DesktopRect();
|
||||||
|
}
|
||||||
|
|
||||||
// Verifies the device index still maps to the same display device, to make
|
// Verifies the device index still maps to the same display device, to make
|
||||||
// sure we are capturing the same device when devices are added or removed.
|
// sure we are capturing the same device when devices are added or removed.
|
||||||
// DeviceKey is documented as reserved, but it actually contains the registry
|
// DeviceKey is documented as reserved, but it actually contains the registry
|
||||||
// key for the device and is unique for each monitor, while DeviceID is not.
|
// key for the device and is unique for each monitor, while DeviceID is not.
|
||||||
if (device_key != device.DeviceKey)
|
if (device_key != device.DeviceKey) {
|
||||||
return DesktopRect();
|
return DesktopRect();
|
||||||
|
}
|
||||||
|
|
||||||
DEVMODEW device_mode;
|
DEVMODEW device_mode;
|
||||||
device_mode.dmSize = sizeof(device_mode);
|
device_mode.dmSize = sizeof(device_mode);
|
||||||
device_mode.dmDriverExtra = 0;
|
device_mode.dmDriverExtra = 0;
|
||||||
result = EnumDisplaySettingsExW(device.DeviceName, ENUM_CURRENT_SETTINGS,
|
result = EnumDisplaySettingsExW(device.DeviceName, ENUM_CURRENT_SETTINGS,
|
||||||
&device_mode, 0);
|
&device_mode, 0);
|
||||||
if (!result)
|
if (!result) {
|
||||||
return DesktopRect();
|
return DesktopRect();
|
||||||
|
}
|
||||||
|
|
||||||
return DesktopRect::MakeXYWH(
|
return DesktopRect::MakeXYWH(
|
||||||
device_mode.dmPosition.x, device_mode.dmPosition.y,
|
device_mode.dmPosition.x, device_mode.dmPosition.y,
|
||||||
|
@ -19,10 +19,6 @@
|
|||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
|
|
||||||
// Outputs the HMONITOR values of all display monitors into |monitors|. Returns
|
|
||||||
// true if succeeded, or false if it fails to enumerate the display monitors.
|
|
||||||
bool GetMonitorList(DesktopCapturer::SourceList* monitors);
|
|
||||||
|
|
||||||
// Output the list of active screens into |screens|. Returns true if succeeded,
|
// Output the list of active screens into |screens|. Returns true if succeeded,
|
||||||
// or false if it fails to enumerate the display devices. If the |device_names|
|
// or false if it fails to enumerate the display devices. If the |device_names|
|
||||||
// is provided, it will be filled with the DISPLAY_DEVICE.DeviceName in UTF-8
|
// is provided, it will be filled with the DISPLAY_DEVICE.DeviceName in UTF-8
|
||||||
@ -31,16 +27,22 @@ bool GetMonitorList(DesktopCapturer::SourceList* monitors);
|
|||||||
bool GetScreenList(DesktopCapturer::SourceList* screens,
|
bool GetScreenList(DesktopCapturer::SourceList* screens,
|
||||||
std::vector<std::string>* device_names = nullptr);
|
std::vector<std::string>* device_names = nullptr);
|
||||||
|
|
||||||
// Returns true if |monitor| is an HMONITOR that represents a valid display
|
// Converts a device index (which are returned by |GetScreenList|) into an
|
||||||
// monitor. Consumers should check that the results of |GetMonitorList| are
|
// HMONITOR.
|
||||||
// valid before use if a WM_DISPLAYCHANGE message has been received.
|
bool GetHmonitorFromDeviceIndex(const DesktopCapturer::SourceId device_index,
|
||||||
bool IsMonitorValid(DesktopCapturer::SourceId monitor);
|
HMONITOR* hmonitor);
|
||||||
|
|
||||||
|
// Returns true if |monitor| represents a valid display
|
||||||
|
// monitor. Consumers should recheck the validity of HMONITORs before use if a
|
||||||
|
// WM_DISPLAYCHANGE message has been received.
|
||||||
|
bool IsMonitorValid(const HMONITOR monitor);
|
||||||
|
|
||||||
// Returns true if |screen| is a valid screen. The screen device key is
|
// Returns true if |screen| is a valid screen. The screen device key is
|
||||||
// returned through |device_key| if the screen is valid. The device key can be
|
// returned through |device_key| if the screen is valid. The device key can be
|
||||||
// used in GetScreenRect to verify the screen matches the previously obtained
|
// used in GetScreenRect to verify the screen matches the previously obtained
|
||||||
// id.
|
// id.
|
||||||
bool IsScreenValid(DesktopCapturer::SourceId screen, std::wstring* device_key);
|
bool IsScreenValid(const DesktopCapturer::SourceId screen,
|
||||||
|
std::wstring* device_key);
|
||||||
|
|
||||||
// Get the rect of the entire system in system coordinate system. I.e. the
|
// Get the rect of the entire system in system coordinate system. I.e. the
|
||||||
// primary monitor always starts from (0, 0).
|
// primary monitor always starts from (0, 0).
|
||||||
@ -49,7 +51,7 @@ DesktopRect GetFullscreenRect();
|
|||||||
// Get the rect of the screen identified by |screen|, relative to the primary
|
// Get the rect of the screen identified by |screen|, relative to the primary
|
||||||
// display's top-left. If the screen device key does not match |device_key|, or
|
// display's top-left. If the screen device key does not match |device_key|, or
|
||||||
// the screen does not exist, or any error happens, an empty rect is returned.
|
// the screen does not exist, or any error happens, an empty rect is returned.
|
||||||
RTC_EXPORT DesktopRect GetScreenRect(DesktopCapturer::SourceId screen,
|
RTC_EXPORT DesktopRect GetScreenRect(const DesktopCapturer::SourceId screen,
|
||||||
const std::wstring& device_key);
|
const std::wstring& device_key);
|
||||||
|
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include "modules/desktop_capture/desktop_capture_types.h"
|
||||||
#include "modules/desktop_capture/desktop_capturer.h"
|
#include "modules/desktop_capture/desktop_capturer.h"
|
||||||
#include "rtc_base/logging.h"
|
#include "rtc_base/logging.h"
|
||||||
#include "test/gtest.h"
|
#include "test/gtest.h"
|
||||||
@ -30,26 +31,29 @@ TEST(ScreenCaptureUtilsTest, GetScreenList) {
|
|||||||
ASSERT_EQ(screens.size(), device_names.size());
|
ASSERT_EQ(screens.size(), device_names.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(ScreenCaptureUtilsTest, GetMonitorList) {
|
TEST(ScreenCaptureUtilsTest, DeviceIndexToHmonitor) {
|
||||||
DesktopCapturer::SourceList monitors;
|
DesktopCapturer::SourceList screens;
|
||||||
|
ASSERT_TRUE(GetScreenList(&screens));
|
||||||
ASSERT_TRUE(GetMonitorList(&monitors));
|
if (screens.size() == 0) {
|
||||||
}
|
|
||||||
|
|
||||||
TEST(ScreenCaptureUtilsTest, IsMonitorValid) {
|
|
||||||
DesktopCapturer::SourceList monitors;
|
|
||||||
|
|
||||||
ASSERT_TRUE(GetMonitorList(&monitors));
|
|
||||||
if (monitors.size() == 0) {
|
|
||||||
RTC_LOG(LS_INFO) << "Skip screen capture test on systems with no monitors.";
|
RTC_LOG(LS_INFO) << "Skip screen capture test on systems with no monitors.";
|
||||||
GTEST_SKIP();
|
GTEST_SKIP();
|
||||||
}
|
}
|
||||||
|
|
||||||
ASSERT_TRUE(IsMonitorValid(monitors[0].id));
|
HMONITOR hmonitor;
|
||||||
|
ASSERT_TRUE(GetHmonitorFromDeviceIndex(screens[0].id, &hmonitor));
|
||||||
|
ASSERT_TRUE(IsMonitorValid(hmonitor));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(ScreenCaptureUtilsTest, InvalidMonitor) {
|
TEST(ScreenCaptureUtilsTest, FullScreenDeviceIndexToHmonitor) {
|
||||||
ASSERT_FALSE(IsMonitorValid(NULL));
|
HMONITOR hmonitor;
|
||||||
|
ASSERT_TRUE(GetHmonitorFromDeviceIndex(kFullDesktopScreenId, &hmonitor));
|
||||||
|
ASSERT_EQ(hmonitor, static_cast<HMONITOR>(0));
|
||||||
|
ASSERT_TRUE(IsMonitorValid(hmonitor));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ScreenCaptureUtilsTest, InvalidDeviceIndexToHmonitor) {
|
||||||
|
HMONITOR hmonitor;
|
||||||
|
ASSERT_FALSE(GetHmonitorFromDeviceIndex(kInvalidScreenId, &hmonitor));
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
@ -36,6 +36,14 @@ HRESULT WgcCaptureSource::GetCaptureItem(
|
|||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool WgcCaptureSource::IsCapturable() {
|
||||||
|
// If we can create a capture item, then we can capture it. Unfortunately,
|
||||||
|
// we can't cache this item because it may be created in a different COM
|
||||||
|
// apartment than where capture will eventually start from.
|
||||||
|
ComPtr<WGC::IGraphicsCaptureItem> item;
|
||||||
|
return SUCCEEDED(CreateCaptureItem(&item));
|
||||||
|
}
|
||||||
|
|
||||||
WgcCaptureSourceFactory::~WgcCaptureSourceFactory() = default;
|
WgcCaptureSourceFactory::~WgcCaptureSourceFactory() = default;
|
||||||
|
|
||||||
WgcWindowSourceFactory::WgcWindowSourceFactory() = default;
|
WgcWindowSourceFactory::WgcWindowSourceFactory() = default;
|
||||||
@ -59,7 +67,10 @@ WgcWindowSource::WgcWindowSource(DesktopCapturer::SourceId source_id)
|
|||||||
WgcWindowSource::~WgcWindowSource() = default;
|
WgcWindowSource::~WgcWindowSource() = default;
|
||||||
|
|
||||||
bool WgcWindowSource::IsCapturable() {
|
bool WgcWindowSource::IsCapturable() {
|
||||||
return IsWindowValidAndVisible(reinterpret_cast<HWND>(GetSourceId()));
|
if (!IsWindowValidAndVisible(reinterpret_cast<HWND>(GetSourceId())))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return WgcCaptureSource::IsCapturable();
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT WgcWindowSource::CreateCaptureItem(
|
HRESULT WgcWindowSource::CreateCaptureItem(
|
||||||
@ -92,15 +103,25 @@ WgcScreenSource::WgcScreenSource(DesktopCapturer::SourceId source_id)
|
|||||||
WgcScreenSource::~WgcScreenSource() = default;
|
WgcScreenSource::~WgcScreenSource() = default;
|
||||||
|
|
||||||
bool WgcScreenSource::IsCapturable() {
|
bool WgcScreenSource::IsCapturable() {
|
||||||
// 0 is the id used to capture all display monitors, so it is valid.
|
if (!hmonitor_) {
|
||||||
if (GetSourceId() == 0)
|
HMONITOR hmon;
|
||||||
return true;
|
if (!GetHmonitorFromDeviceIndex(GetSourceId(), &hmon))
|
||||||
|
return false;
|
||||||
|
|
||||||
return IsMonitorValid(GetSourceId());
|
hmonitor_ = hmon;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!IsMonitorValid(*hmonitor_))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return WgcCaptureSource::IsCapturable();
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT WgcScreenSource::CreateCaptureItem(
|
HRESULT WgcScreenSource::CreateCaptureItem(
|
||||||
ComPtr<WGC::IGraphicsCaptureItem>* result) {
|
ComPtr<WGC::IGraphicsCaptureItem>* result) {
|
||||||
|
if (!hmonitor_)
|
||||||
|
return E_ABORT;
|
||||||
|
|
||||||
if (!ResolveCoreWinRTDelayload())
|
if (!ResolveCoreWinRTDelayload())
|
||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
|
|
||||||
@ -112,8 +133,7 @@ HRESULT WgcScreenSource::CreateCaptureItem(
|
|||||||
return hr;
|
return hr;
|
||||||
|
|
||||||
ComPtr<WGC::IGraphicsCaptureItem> item;
|
ComPtr<WGC::IGraphicsCaptureItem> item;
|
||||||
hr = interop->CreateForMonitor(reinterpret_cast<HMONITOR>(GetSourceId()),
|
hr = interop->CreateForMonitor(*hmonitor_, IID_PPV_ARGS(&item));
|
||||||
IID_PPV_ARGS(&item));
|
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
return hr;
|
return hr;
|
||||||
|
|
||||||
|
@ -13,9 +13,12 @@
|
|||||||
|
|
||||||
#include <windows.graphics.capture.h>
|
#include <windows.graphics.capture.h>
|
||||||
#include <wrl/client.h>
|
#include <wrl/client.h>
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
|
#include "absl/types/optional.h"
|
||||||
#include "modules/desktop_capture/desktop_capturer.h"
|
#include "modules/desktop_capture/desktop_capturer.h"
|
||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
|
|
||||||
// Abstract class to represent the source that WGC-based capturers capture
|
// Abstract class to represent the source that WGC-based capturers capture
|
||||||
@ -27,7 +30,7 @@ class WgcCaptureSource {
|
|||||||
explicit WgcCaptureSource(DesktopCapturer::SourceId source_id);
|
explicit WgcCaptureSource(DesktopCapturer::SourceId source_id);
|
||||||
virtual ~WgcCaptureSource();
|
virtual ~WgcCaptureSource();
|
||||||
|
|
||||||
virtual bool IsCapturable() = 0;
|
virtual bool IsCapturable();
|
||||||
HRESULT GetCaptureItem(
|
HRESULT GetCaptureItem(
|
||||||
Microsoft::WRL::ComPtr<
|
Microsoft::WRL::ComPtr<
|
||||||
ABI::Windows::Graphics::Capture::IGraphicsCaptureItem>* result);
|
ABI::Windows::Graphics::Capture::IGraphicsCaptureItem>* result);
|
||||||
@ -41,7 +44,7 @@ class WgcCaptureSource {
|
|||||||
private:
|
private:
|
||||||
Microsoft::WRL::ComPtr<ABI::Windows::Graphics::Capture::IGraphicsCaptureItem>
|
Microsoft::WRL::ComPtr<ABI::Windows::Graphics::Capture::IGraphicsCaptureItem>
|
||||||
item_;
|
item_;
|
||||||
DesktopCapturer::SourceId source_id_;
|
const DesktopCapturer::SourceId source_id_;
|
||||||
};
|
};
|
||||||
|
|
||||||
class WgcCaptureSourceFactory {
|
class WgcCaptureSourceFactory {
|
||||||
@ -115,6 +118,12 @@ class WgcScreenSource final : public WgcCaptureSource {
|
|||||||
Microsoft::WRL::ComPtr<
|
Microsoft::WRL::ComPtr<
|
||||||
ABI::Windows::Graphics::Capture::IGraphicsCaptureItem>* result)
|
ABI::Windows::Graphics::Capture::IGraphicsCaptureItem>* result)
|
||||||
override;
|
override;
|
||||||
|
|
||||||
|
// To maintain compatibility with other capturers, this class accepts a
|
||||||
|
// device index as it's SourceId. However, WGC requires we use an HMONITOR to
|
||||||
|
// describe which screen to capture. So, we internally convert the supplied
|
||||||
|
// device index into an HMONITOR when |IsCapturable()| is called.
|
||||||
|
absl::optional<HMONITOR> hmonitor_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
|
|
||||||
#include <d3d11.h>
|
#include <d3d11.h>
|
||||||
#include <wrl/client.h>
|
#include <wrl/client.h>
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
@ -62,7 +63,7 @@ class ScreenEnumerator final : public SourceEnumerator {
|
|||||||
~ScreenEnumerator() override = default;
|
~ScreenEnumerator() override = default;
|
||||||
|
|
||||||
bool FindAllSources(DesktopCapturer::SourceList* sources) override {
|
bool FindAllSources(DesktopCapturer::SourceList* sources) override {
|
||||||
return webrtc::GetMonitorList(sources);
|
return webrtc::GetScreenList(sources);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user