Mapping screen id from DirectX capturer to GDI capturer

This change ensures DirectX capturer to return the same ScreenId as GDI capturer
for each monitor. So MouseCursoeMonitor can work correctly with the DirectX
capturer.

This is a temporary fix of webrtc:7950.

Bug: webrtc:7950
Change-Id: Icd3f40556701811c21c773a39260a74db43979f3
Reviewed-on: https://chromium-review.googlesource.com/571101
Commit-Queue: Zijie He <zijiehe@chromium.org>
Reviewed-by: Sergey Ulanov <sergeyu@chromium.org>
Cr-Commit-Position: refs/heads/master@{#19079}
This commit is contained in:
Zijie He 2017-07-17 20:33:47 -07:00 committed by Commit Bot
parent 8d2c235b75
commit 3e45cb577e
7 changed files with 140 additions and 16 deletions

View File

@ -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",

View File

@ -12,6 +12,10 @@
#include <windows.h>
#include <string>
#include <vector>
#include "webrtc/modules/desktop_capture/desktop_capturer.h"
#include "webrtc/rtc_base/checks.h"
#include "webrtc/rtc_base/win32.h"

View File

@ -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<std::string>* device_names = nullptr);

View File

@ -22,9 +22,9 @@ TEST(ScreenCaptureUtilsTest, GetScreenList) {
DesktopCapturer::SourceList screens;
std::vector<std::string> 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());
}

View File

@ -10,10 +10,13 @@
#include "webrtc/modules/desktop_capture/win/screen_capturer_win_directx.h"
#include <algorithm>
#include <string>
#include <utility>
#include <vector>
#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<std::string>& device_names,
DesktopCapturer::SourceList* screens) {
RTC_DCHECK(screens->empty());
DesktopCapturer::SourceList gdi_screens;
std::vector<std::string> 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<std::string>& 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<int>(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<std::string> 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<std::string> 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

View File

@ -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<std::string>& 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<std::string>& device_names);
explicit ScreenCapturerWinDirectx();
~ScreenCapturerWinDirectx() override;

View File

@ -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 <vector>
#include <string>
#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<std::string> 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<int>(i));
}
}
} // namespace webrtc