From 4ff4208c21d77ed235e5eb15e65a458132b3d1ca Mon Sep 17 00:00:00 2001 From: zijiehe Date: Thu, 13 Jul 2017 16:05:24 -0700 Subject: [PATCH] Output DeviceName from various windows ScreenCapturer related implementations Both DXGI_OUTPUT_DESC and DISPLAY_DEVICE contain the DeviceName, which may be able to map a DirectX screen id with the GDI screen id. So this change exports the field from both DirectX and GDI implementations. BUG=webrtc:7950 Review-Url: https://codereview.webrtc.org/2971393002 Cr-Commit-Position: refs/heads/master@{#19010} --- webrtc/modules/desktop_capture/BUILD.gn | 1 + .../win/dxgi_adapter_duplicator.cc | 5 +++ .../win/dxgi_adapter_duplicator.h | 4 +++ .../win/dxgi_duplicator_controller.cc | 20 ++++++++++++ .../win/dxgi_duplicator_controller.h | 9 ++++++ .../win/dxgi_output_duplicator.cc | 2 ++ .../win/dxgi_output_duplicator.h | 5 +++ .../win/screen_capture_utils.cc | 12 +++++-- .../win/screen_capture_utils.h | 11 +++++-- .../win/screen_capture_utils_unittest.cc | 32 +++++++++++++++++++ 10 files changed, 97 insertions(+), 4 deletions(-) create mode 100644 webrtc/modules/desktop_capture/win/screen_capture_utils_unittest.cc diff --git a/webrtc/modules/desktop_capture/BUILD.gn b/webrtc/modules/desktop_capture/BUILD.gn index f7d6f472da..4682ce8c50 100644 --- a/webrtc/modules/desktop_capture/BUILD.gn +++ b/webrtc/modules/desktop_capture/BUILD.gn @@ -88,6 +88,7 @@ if (rtc_include_tests) { "win/cursor_unittest.cc", "win/cursor_unittest_resources.h", "win/cursor_unittest_resources.rc", + "win/screen_capture_utils_unittest.cc", ] deps = [ ":desktop_capture", diff --git a/webrtc/modules/desktop_capture/win/dxgi_adapter_duplicator.cc b/webrtc/modules/desktop_capture/win/dxgi_adapter_duplicator.cc index 4870c754d2..c2a0794fe3 100644 --- a/webrtc/modules/desktop_capture/win/dxgi_adapter_duplicator.cc +++ b/webrtc/modules/desktop_capture/win/dxgi_adapter_duplicator.cc @@ -146,6 +146,11 @@ DesktopRect DxgiAdapterDuplicator::ScreenRect(int id) const { return duplicators_[id].desktop_rect(); } +const std::string& DxgiAdapterDuplicator::GetDeviceName(int id) const { + RTC_DCHECK(id >= 0 && id < static_cast(duplicators_.size())); + return duplicators_[id].device_name(); +} + int DxgiAdapterDuplicator::screen_count() const { return static_cast(duplicators_.size()); } diff --git a/webrtc/modules/desktop_capture/win/dxgi_adapter_duplicator.h b/webrtc/modules/desktop_capture/win/dxgi_adapter_duplicator.h index cf33353f22..0fa51ac920 100644 --- a/webrtc/modules/desktop_capture/win/dxgi_adapter_duplicator.h +++ b/webrtc/modules/desktop_capture/win/dxgi_adapter_duplicator.h @@ -59,6 +59,10 @@ class DxgiAdapterDuplicator { // should be between [0, screen_count()). DesktopRect ScreenRect(int id) const; + // Returns the device name of one screen owned by this DxgiAdapterDuplicator + // in utf8 encoding. |id| should be between [0, screen_count()). + const std::string& GetDeviceName(int id) const; + // Returns the count of screens owned by this DxgiAdapterDuplicator. These // screens can be retrieved by an interger in the range of // [0, screen_count()). diff --git a/webrtc/modules/desktop_capture/win/dxgi_duplicator_controller.cc b/webrtc/modules/desktop_capture/win/dxgi_duplicator_controller.cc index 1c015e4a82..83e0fda5ff 100644 --- a/webrtc/modules/desktop_capture/win/dxgi_duplicator_controller.cc +++ b/webrtc/modules/desktop_capture/win/dxgi_duplicator_controller.cc @@ -114,6 +114,16 @@ int DxgiDuplicatorController::ScreenCount() { return 0; } +bool DxgiDuplicatorController::GetDeviceNames( + std::vector* output) { + rtc::CritScope lock(&lock_); + if (Initialize()) { + GetDeviceNamesUnlocked(output); + return true; + } + return false; +} + DxgiDuplicatorController::Result DxgiDuplicatorController::DoDuplicate(DxgiFrame* frame, int monitor_id) { RTC_DCHECK(frame); @@ -370,6 +380,16 @@ int DxgiDuplicatorController::ScreenCountUnlocked() const { return result; } +void DxgiDuplicatorController::GetDeviceNamesUnlocked( + std::vector* output) const { + RTC_DCHECK(output); + for (auto& duplicator : duplicators_) { + for (int i = 0; i < duplicator.screen_count(); i++) { + output->push_back(duplicator.GetDeviceName(i)); + } + } +} + DesktopSize DxgiDuplicatorController::SelectedDesktopSize( int monitor_id) const { if (monitor_id < 0) { diff --git a/webrtc/modules/desktop_capture/win/dxgi_duplicator_controller.h b/webrtc/modules/desktop_capture/win/dxgi_duplicator_controller.h index 43768d9899..0b0990d73d 100644 --- a/webrtc/modules/desktop_capture/win/dxgi_duplicator_controller.h +++ b/webrtc/modules/desktop_capture/win/dxgi_duplicator_controller.h @@ -14,6 +14,7 @@ #include #include +#include #include #include "webrtc/modules/desktop_capture/desktop_geometry.h" @@ -101,6 +102,12 @@ class DxgiDuplicatorController { // support DXGI based capturer, this function returns 0. int ScreenCount(); + // Returns the device names of all screens on the system in utf8 encoding. + // These screens can be retrieved by an integer in the range of + // [0, output->size()). If system does not support DXGI based capturer, this + // function returns false. + bool GetDeviceNames(std::vector* output); + private: // DxgiFrameContext calls private Unregister(Context*) function in Reset(). friend void DxgiFrameContext::Reset(); @@ -182,6 +189,8 @@ class DxgiDuplicatorController { int ScreenCountUnlocked() const; + void GetDeviceNamesUnlocked(std::vector* output) const; + // Returns the desktop size of the selected screen |monitor_id|. Setting // |monitor_id| < 0 to return the entire screen size. DesktopSize SelectedDesktopSize(int monitor_id) const; diff --git a/webrtc/modules/desktop_capture/win/dxgi_output_duplicator.cc b/webrtc/modules/desktop_capture/win/dxgi_output_duplicator.cc index 741d5dad3f..21453b28ef 100644 --- a/webrtc/modules/desktop_capture/win/dxgi_output_duplicator.cc +++ b/webrtc/modules/desktop_capture/win/dxgi_output_duplicator.cc @@ -23,6 +23,7 @@ #include "webrtc/modules/desktop_capture/win/dxgi_texture_staging.h" #include "webrtc/rtc_base/checks.h" #include "webrtc/rtc_base/logging.h" +#include "webrtc/rtc_base/win32.h" namespace webrtc { @@ -64,6 +65,7 @@ DxgiOutputDuplicator::DxgiOutputDuplicator(const D3dDevice& device, const DXGI_OUTPUT_DESC& desc) : device_(device), output_(output), + device_name_(rtc::ToUtf8(desc.DeviceName)), desktop_rect_(RECTToDesktopRect(desc.DesktopCoordinates)) { RTC_DCHECK(output_); RTC_DCHECK(!desktop_rect_.is_empty()); diff --git a/webrtc/modules/desktop_capture/win/dxgi_output_duplicator.h b/webrtc/modules/desktop_capture/win/dxgi_output_duplicator.h index 0aa7eddcaa..47e078f4ad 100644 --- a/webrtc/modules/desktop_capture/win/dxgi_output_duplicator.h +++ b/webrtc/modules/desktop_capture/win/dxgi_output_duplicator.h @@ -17,6 +17,7 @@ #include #include +#include #include #include "webrtc/modules/desktop_capture/desktop_frame_rotation.h" @@ -68,6 +69,9 @@ class DxgiOutputDuplicator { // Returns the desktop rect covered by this DxgiOutputDuplicator. DesktopRect desktop_rect() const { return desktop_rect_; } + // Returns the device name from DXGI_OUTPUT_DESC in utf8 encoding. + const std::string& device_name() const { return device_name_; } + void Setup(Context* context); void Unregister(const Context* const context); @@ -112,6 +116,7 @@ class DxgiOutputDuplicator { const D3dDevice device_; const Microsoft::WRL::ComPtr output_; + const std::string device_name_; DesktopRect desktop_rect_; Microsoft::WRL::ComPtr duplication_; DXGI_OUTDUPL_DESC desc_; diff --git a/webrtc/modules/desktop_capture/win/screen_capture_utils.cc b/webrtc/modules/desktop_capture/win/screen_capture_utils.cc index 9fa5c8b12d..d06c869567 100644 --- a/webrtc/modules/desktop_capture/win/screen_capture_utils.cc +++ b/webrtc/modules/desktop_capture/win/screen_capture_utils.cc @@ -13,11 +13,16 @@ #include #include "webrtc/rtc_base/checks.h" +#include "webrtc/rtc_base/win32.h" namespace webrtc { -bool GetScreenList(DesktopCapturer::SourceList* screens) { - RTC_DCHECK(screens->size() == 0); +bool GetScreenList(DesktopCapturer::SourceList* screens, + std::vector* device_names /* = nullptr */) { + RTC_DCHECK_EQ(screens->size(), 0U); + if (device_names) { + RTC_DCHECK_EQ(device_names->size(), 0U); + } BOOL enum_result = TRUE; for (int device_index = 0;; ++device_index) { @@ -34,6 +39,9 @@ bool GetScreenList(DesktopCapturer::SourceList* screens) { continue; screens->push_back({device_index, std::string()}); + if (device_names) { + device_names->push_back(rtc::ToUtf8(device.DeviceName)); + } } return true; } diff --git a/webrtc/modules/desktop_capture/win/screen_capture_utils.h b/webrtc/modules/desktop_capture/win/screen_capture_utils.h index 751588b47e..90dd38ff22 100644 --- a/webrtc/modules/desktop_capture/win/screen_capture_utils.h +++ b/webrtc/modules/desktop_capture/win/screen_capture_utils.h @@ -11,13 +11,20 @@ #ifndef WEBRTC_MODULES_DESKTOP_CAPTURE_WIN_SCREEN_CAPTURE_UTILS_H_ #define WEBRTC_MODULES_DESKTOP_CAPTURE_WIN_SCREEN_CAPTURE_UTILS_H_ +#include +#include + #include "webrtc/modules/desktop_capture/desktop_capturer.h" namespace webrtc { // Output the list of active screens into |screens|. Returns true if succeeded, -// or false if it fails to enumerate the display devices. -bool GetScreenList(DesktopCapturer::SourceList* screens); +// 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 +// encoding. Once this function returns true, consumers can always assume that +// |screens|[i] and |device_names|[i] indicate the same monitor on the system. +bool GetScreenList(DesktopCapturer::SourceList* screens, + std::vector* device_names = nullptr); // 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 diff --git a/webrtc/modules/desktop_capture/win/screen_capture_utils_unittest.cc b/webrtc/modules/desktop_capture/win/screen_capture_utils_unittest.cc new file mode 100644 index 0000000000..9c852534b4 --- /dev/null +++ b/webrtc/modules/desktop_capture/win/screen_capture_utils_unittest.cc @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include "webrtc/modules/desktop_capture/win/screen_capture_utils.h" + +#include +#include + +#include "webrtc/modules/desktop_capture/desktop_capturer.h" +#include "webrtc/test/gtest.h" + +namespace webrtc { + +TEST(ScreenCaptureUtilsTest, GetScreenList) { + DesktopCapturer::SourceList screens; + std::vector device_names; + + GetScreenList(&screens); + screens.clear(); + GetScreenList(&screens, &device_names); + + ASSERT_EQ(screens.size(), device_names.size()); +} + +} // namespace webrtc