diff --git a/webrtc/modules/desktop_capture/BUILD.gn b/webrtc/modules/desktop_capture/BUILD.gn index 4682ce8c50..889f0fad4b 100644 --- a/webrtc/modules/desktop_capture/BUILD.gn +++ b/webrtc/modules/desktop_capture/BUILD.gn @@ -89,6 +89,7 @@ if (rtc_include_tests) { "win/cursor_unittest_resources.h", "win/cursor_unittest_resources.rc", "win/screen_capture_utils_unittest.cc", + "win/screen_capturer_win_directx_unittest.cc", ] deps = [ ":desktop_capture", diff --git a/webrtc/modules/desktop_capture/win/screen_capture_utils.cc b/webrtc/modules/desktop_capture/win/screen_capture_utils.cc index d06c869567..e640bde277 100644 --- a/webrtc/modules/desktop_capture/win/screen_capture_utils.cc +++ b/webrtc/modules/desktop_capture/win/screen_capture_utils.cc @@ -12,6 +12,10 @@ #include +#include +#include + +#include "webrtc/modules/desktop_capture/desktop_capturer.h" #include "webrtc/rtc_base/checks.h" #include "webrtc/rtc_base/win32.h" diff --git a/webrtc/modules/desktop_capture/win/screen_capture_utils.h b/webrtc/modules/desktop_capture/win/screen_capture_utils.h index 90dd38ff22..73754b2eea 100644 --- a/webrtc/modules/desktop_capture/win/screen_capture_utils.h +++ b/webrtc/modules/desktop_capture/win/screen_capture_utils.h @@ -21,7 +21,7 @@ namespace webrtc { // 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| // 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 +// encoding. If 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); diff --git a/webrtc/modules/desktop_capture/win/screen_capture_utils_unittest.cc b/webrtc/modules/desktop_capture/win/screen_capture_utils_unittest.cc index 9c852534b4..47f02e4551 100644 --- a/webrtc/modules/desktop_capture/win/screen_capture_utils_unittest.cc +++ b/webrtc/modules/desktop_capture/win/screen_capture_utils_unittest.cc @@ -22,9 +22,9 @@ TEST(ScreenCaptureUtilsTest, GetScreenList) { DesktopCapturer::SourceList screens; std::vector device_names; - GetScreenList(&screens); + ASSERT_TRUE(GetScreenList(&screens)); screens.clear(); - GetScreenList(&screens, &device_names); + ASSERT_TRUE(GetScreenList(&screens, &device_names)); ASSERT_EQ(screens.size(), device_names.size()); } diff --git a/webrtc/modules/desktop_capture/win/screen_capturer_win_directx.cc b/webrtc/modules/desktop_capture/win/screen_capturer_win_directx.cc index 722353e4f3..c4d778f8f8 100644 --- a/webrtc/modules/desktop_capture/win/screen_capturer_win_directx.cc +++ b/webrtc/modules/desktop_capture/win/screen_capturer_win_directx.cc @@ -10,10 +10,13 @@ #include "webrtc/modules/desktop_capture/win/screen_capturer_win_directx.h" +#include #include #include +#include #include "webrtc/modules/desktop_capture/desktop_frame.h" +#include "webrtc/modules/desktop_capture/win/screen_capture_utils.h" #include "webrtc/rtc_base/checks.h" #include "webrtc/rtc_base/logging.h" #include "webrtc/rtc_base/ptr_util.h" @@ -41,6 +44,60 @@ bool ScreenCapturerWinDirectx::IsCurrentSessionSupported() { return DxgiDuplicatorController::IsCurrentSessionSupported(); } +// static +bool ScreenCapturerWinDirectx::GetScreenListFromDeviceNames( + const std::vector& device_names, + DesktopCapturer::SourceList* screens) { + RTC_DCHECK(screens->empty()); + + DesktopCapturer::SourceList gdi_screens; + std::vector gdi_names; + if (!GetScreenList(&gdi_screens, &gdi_names)) { + return false; + } + + RTC_DCHECK_EQ(gdi_screens.size(), gdi_names.size()); + + ScreenId max_screen_id = -1; + for (const DesktopCapturer::Source& screen : gdi_screens) { + max_screen_id = std::max(max_screen_id, screen.id); + } + + for (const auto& device_name : device_names) { + const auto it = std::find( + gdi_names.begin(), gdi_names.end(), device_name); + if (it == gdi_names.end()) { + // devices_names[i] has not been found in gdi_names, so use max_screen_id. + max_screen_id++; + screens->push_back({ max_screen_id }); + } else { + screens->push_back({ gdi_screens[it - gdi_names.begin()] }); + } + } + + return true; +} + +// static +int ScreenCapturerWinDirectx::GetIndexFromScreenId( + ScreenId id, + const std::vector& device_names) { + DesktopCapturer::SourceList screens; + if (!GetScreenListFromDeviceNames(device_names, &screens)) { + return -1; + } + + RTC_DCHECK_EQ(device_names.size(), screens.size()); + + for (size_t i = 0; i < screens.size(); i++) { + if (screens[i].id == id) { + return static_cast(i); + } + } + + return -1; +} + ScreenCapturerWinDirectx::ScreenCapturerWinDirectx() : controller_(DxgiDuplicatorController::Instance()) {} @@ -115,29 +172,33 @@ void ScreenCapturerWinDirectx::CaptureFrame() { } bool ScreenCapturerWinDirectx::GetSourceList(SourceList* sources) { - int screen_count = controller_->ScreenCount(); - for (int i = 0; i < screen_count; i++) { - sources->push_back({i}); + std::vector device_names; + if (!controller_->GetDeviceNames(&device_names)) { + return false; } - return true; + + return GetScreenListFromDeviceNames(device_names, sources); } bool ScreenCapturerWinDirectx::SelectSource(SourceId id) { - if (id == current_screen_id_) { - return true; - } - if (id == kFullDesktopScreenId) { current_screen_id_ = id; return true; } - int screen_count = controller_->ScreenCount(); - if (id >= 0 && id < screen_count) { - current_screen_id_ = id; - return true; + std::vector device_names; + if (!controller_->GetDeviceNames(&device_names)) { + return false; } - return false; + + int index; + index = GetIndexFromScreenId(id, device_names); + if (index == -1) { + return false; + } + + current_screen_id_ = index; + return true; } } // namespace webrtc diff --git a/webrtc/modules/desktop_capture/win/screen_capturer_win_directx.h b/webrtc/modules/desktop_capture/win/screen_capturer_win_directx.h index f383303b5d..b91882c655 100644 --- a/webrtc/modules/desktop_capture/win/screen_capturer_win_directx.h +++ b/webrtc/modules/desktop_capture/win/screen_capturer_win_directx.h @@ -51,6 +51,23 @@ class ScreenCapturerWinDirectx : public DesktopCapturer { // always try IsSupported() function. static bool IsCurrentSessionSupported(); + // Maps |device_names| with the result from GetScreenList() and creates a new + // SourceList to include only the ones in |device_names|. If this function + // returns true, consumers can always assume |device_names|.size() equals to + // |screens|->size(), meanwhile |device_names|[i] and |screens|[i] indicate + // the same monitor on the system. + // Public for test only. + static bool GetScreenListFromDeviceNames( + const std::vector& device_names, + DesktopCapturer::SourceList* screens); + + // Maps |id| with the result from GetScreenListFromDeviceNames() and returns + // the index of the entity in |device_names|. This function returns -1 if |id| + // cannot be found. + // Public for test only. + static int GetIndexFromScreenId(ScreenId id, + const std::vector& device_names); + explicit ScreenCapturerWinDirectx(); ~ScreenCapturerWinDirectx() override; diff --git a/webrtc/modules/desktop_capture/win/screen_capturer_win_directx_unittest.cc b/webrtc/modules/desktop_capture/win/screen_capturer_win_directx_unittest.cc new file mode 100644 index 0000000000..577be0aa97 --- /dev/null +++ b/webrtc/modules/desktop_capture/win/screen_capturer_win_directx_unittest.cc @@ -0,0 +1,41 @@ +/* + * 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_capturer_win_directx.h" + +#include +#include + +#include "webrtc/modules/desktop_capture/desktop_capturer.h" +#include "webrtc/test/gtest.h" + +namespace webrtc { + +// This test cannot ensure GetScreenListFromDeviceNames() won't reorder the +// devices in its output, since the device name is missing. +TEST(ScreenCaptureUtilsTest, GetScreenListFromDeviceNamesAndGetIndex) { + const std::vector device_names = { + "\\\\.\\DISPLAY0", + "\\\\.\\DISPLAY1", + "\\\\.\\DISPLAY2", + }; + DesktopCapturer::SourceList screens; + ASSERT_TRUE(ScreenCapturerWinDirectx::GetScreenListFromDeviceNames( + device_names, &screens)); + ASSERT_EQ(device_names.size(), screens.size()); + + for (size_t i = 0; i < screens.size(); i++) { + ASSERT_EQ(ScreenCapturerWinDirectx::GetIndexFromScreenId( + screens[i].id, device_names), + static_cast(i)); + } +} + +} // namespace webrtc