Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1548)

Unified Diff: webrtc/modules/desktop_capture/win/dxgi_duplicator_controller.cc

Issue 2788863006: Merge ScreenCapturerWinDirectx::frames_ and contexts_ (Closed)
Patch Set: Resolve review comments Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: webrtc/modules/desktop_capture/win/dxgi_duplicator_controller.cc
diff --git a/webrtc/modules/desktop_capture/win/dxgi_duplicator_controller.cc b/webrtc/modules/desktop_capture/win/dxgi_duplicator_controller.cc
index a5f09f00407b301b112ecd7d6d2d0b62d4508564..12876c2c89d4612731de10c6e1ba51932f1d8003 100644
--- a/webrtc/modules/desktop_capture/win/dxgi_duplicator_controller.cc
+++ b/webrtc/modules/desktop_capture/win/dxgi_duplicator_controller.cc
@@ -18,21 +18,12 @@
#include "webrtc/base/checks.h"
#include "webrtc/base/timeutils.h"
#include "webrtc/modules/desktop_capture/desktop_capture_types.h"
+#include "webrtc/modules/desktop_capture/win/dxgi_frame.h"
#include "webrtc/modules/desktop_capture/win/screen_capture_utils.h"
#include "webrtc/system_wrappers/include/sleep.h"
namespace webrtc {
-DxgiDuplicatorController::Context::Context() = default;
-
-DxgiDuplicatorController::Context::~Context() {
- DxgiDuplicatorController::Instance()->Unregister(this);
-}
-
-void DxgiDuplicatorController::Context::Reset() {
- identity_ = 0;
-}
-
// static
DxgiDuplicatorController* DxgiDuplicatorController::Instance() {
// The static instance won't be deleted to ensure it can be used by other
@@ -53,11 +44,6 @@ bool DxgiDuplicatorController::IsSupported() {
return Initialize();
}
-void DxgiDuplicatorController::Reset() {
- rtc::CritScope lock(&lock_);
- Deinitialize();
-}
-
bool DxgiDuplicatorController::RetrieveD3dInfo(D3dInfo* info) {
rtc::CritScope lock(&lock_);
if (!Initialize()) {
@@ -67,6 +53,17 @@ bool DxgiDuplicatorController::RetrieveD3dInfo(D3dInfo* info) {
return true;
}
+DxgiDuplicatorController::Result
+DxgiDuplicatorController::Duplicate(DxgiFrame* frame) {
+ return DoDuplicate(frame, -1);
+}
+
+DxgiDuplicatorController::Result
+DxgiDuplicatorController::DuplicateMonitor(DxgiFrame* frame, int monitor_id) {
+ RTC_DCHECK_GE(monitor_id, 0);
+ return DoDuplicate(frame, monitor_id);
+}
+
DesktopVector DxgiDuplicatorController::dpi() {
rtc::CritScope lock(&lock_);
if (Initialize()) {
@@ -75,38 +72,61 @@ DesktopVector DxgiDuplicatorController::dpi() {
return DesktopVector();
}
-DesktopRect DxgiDuplicatorController::desktop_rect() {
+int DxgiDuplicatorController::ScreenCount() {
rtc::CritScope lock(&lock_);
if (Initialize()) {
- return desktop_rect_;
+ return ScreenCountUnlocked();
}
- return DesktopRect();
+ return 0;
}
-DesktopSize DxgiDuplicatorController::desktop_size() {
- DesktopRect rect = desktop_rect();
- return DesktopSize(rect.right(), rect.bottom());
-}
-
-DesktopRect DxgiDuplicatorController::ScreenRect(int id) {
- RTC_DCHECK(id >= 0);
+DxgiDuplicatorController::Result
+DxgiDuplicatorController::DoDuplicate(DxgiFrame* frame, int monitor_id) {
+ RTC_DCHECK(frame);
rtc::CritScope lock(&lock_);
+
+ // The dxgi components and APIs do not update the screen resolution without
+ // a reinitialization. So we use the GetDC() function to retrieve the screen
+ // resolution to decide whether dxgi components need to be reinitialized.
+ // If the screen resolution changed, it's very likely the next Duplicate()
+ // function call will fail because of a missing monitor or the frame size is
+ // not enough to store the output. So we reinitialize dxgi components in-place
+ // to avoid a capture failure.
+ // But there is no guarantee GetDC() function returns the same resolution as
+ // dxgi APIs, we still rely on dxgi components to return the output frame
+ // size.
+ // TODO(zijiehe): Confirm whether IDXGIOutput::GetDesc() and
+ // IDXGIOutputDuplication::GetDesc() can detect the resolution change without
+ // reinitialization.
+ if (resolution_change_detector_.IsChanged(
+ GetScreenRect(kFullDesktopScreenId, std::wstring()).size())) {
+ Deinitialize();
+ }
+
if (!Initialize()) {
- return DesktopRect();
+ // Cannot initialize COM components now, display mode may be changing.
+ return Result::INITIALIZATION_FAILED;
}
- for (size_t i = 0; i < duplicators_.size(); i++) {
- if (id >= duplicators_[i].screen_count()) {
- id -= duplicators_[i].screen_count();
- } else {
- return duplicators_[i].ScreenRect(id);
- }
+
+ if (!frame->Prepare(SelectedDesktopSize(monitor_id), monitor_id)) {
+ return Result::FRAME_PREPARE_FAILED;
}
- return DesktopRect();
-}
-int DxgiDuplicatorController::ScreenCount() {
- rtc::CritScope lock(&lock_);
- return ScreenCountUnlocked();
+ frame->frame()->mutable_updated_region()->Clear();
+
+ if (DoDuplicateUnlocked(frame->context(), monitor_id, frame->frame())) {
+ return Result::SUCCEEDED;
+ }
+ if (monitor_id >= ScreenCountUnlocked()) {
+ // It's a user error to provide a |monitor_id| larger than screen count. We
+ // do not need to deinitialize.
+ return Result::INVALID_MONITOR_ID;
+ }
+
+ // If the |monitor_id| is valid, but DoDuplicateUnlocked() failed, something
+ // must be wrong from capturer APIs. We should Deinitialize().
+ Deinitialize();
+ return Result::DUPLICATION_FAILED;
}
void DxgiDuplicatorController::Unregister(const Context* const context) {
@@ -117,7 +137,7 @@ void DxgiDuplicatorController::Unregister(const Context* const context) {
return;
}
for (size_t i = 0; i < duplicators_.size(); i++) {
- duplicators_[i].Unregister(&context->contexts_[i]);
+ duplicators_[i].Unregister(&context->contexts[i]);
}
}
@@ -194,66 +214,26 @@ void DxgiDuplicatorController::Deinitialize() {
bool DxgiDuplicatorController::ContextExpired(
const Context* const context) const {
- return context->identity_ != identity_ ||
- context->contexts_.size() != duplicators_.size();
+ RTC_DCHECK(context);
+ return context->controller_id != identity_ ||
+ context->contexts.size() != duplicators_.size();
}
void DxgiDuplicatorController::Setup(Context* context) {
if (ContextExpired(context)) {
- context->contexts_.clear();
- context->contexts_.resize(duplicators_.size());
+ RTC_DCHECK(context);
+ context->contexts.clear();
+ context->contexts.resize(duplicators_.size());
for (size_t i = 0; i < duplicators_.size(); i++) {
- duplicators_[i].Setup(&context->contexts_[i]);
+ duplicators_[i].Setup(&context->contexts[i]);
}
- context->identity_ = identity_;
+ context->controller_id = identity_;
}
}
-bool DxgiDuplicatorController::Duplicate(Context* context,
- SharedDesktopFrame* target) {
- return DoDuplicate(context, -1, target);
-}
-
-bool DxgiDuplicatorController::DuplicateMonitor(Context* context,
- int monitor_id,
- SharedDesktopFrame* target) {
- RTC_DCHECK_GE(monitor_id, 0);
- return DoDuplicate(context, monitor_id, target);
-}
-
-bool DxgiDuplicatorController::DoDuplicate(Context* context,
- int monitor_id,
- SharedDesktopFrame* target) {
- RTC_DCHECK(target);
- target->mutable_updated_region()->Clear();
- rtc::CritScope lock(&lock_);
- if (DoDuplicateUnlocked(context, monitor_id, target)) {
- return true;
- }
- if (monitor_id < ScreenCountUnlocked()) {
- // It's a user error to provide a |monitor_id| larger than screen count. We
- // do not need to deinitialize.
- Deinitialize();
- }
- return false;
-}
-
bool DxgiDuplicatorController::DoDuplicateUnlocked(Context* context,
int monitor_id,
SharedDesktopFrame* target) {
- if (!Initialize()) {
- // Cannot initialize COM components now, display mode may be changing.
- return false;
- }
-
- if (resolution_change_detector_.IsChanged(
- GetScreenRect(kFullDesktopScreenId, std::wstring()).size())) {
- // Resolution of entire screen has been changed, which usually means a new
- // monitor has been attached or one has been removed. The simplest way is to
- // Deinitialize() and returns false to indicate downstream components.
- return false;
- }
-
Setup(context);
if (!EnsureFrameCaptured(context, target)) {
@@ -279,7 +259,7 @@ bool DxgiDuplicatorController::DoDuplicateUnlocked(Context* context,
bool DxgiDuplicatorController::DoDuplicateAll(Context* context,
SharedDesktopFrame* target) {
for (size_t i = 0; i < duplicators_.size(); i++) {
- if (!duplicators_[i].Duplicate(&context->contexts_[i], target)) {
+ if (!duplicators_[i].Duplicate(&context->contexts[i], target)) {
return false;
}
}
@@ -290,12 +270,12 @@ bool DxgiDuplicatorController::DoDuplicateOne(Context* context,
int monitor_id,
SharedDesktopFrame* target) {
RTC_DCHECK(monitor_id >= 0);
- for (size_t i = 0; i < duplicators_.size() && i < context->contexts_.size();
+ for (size_t i = 0; i < duplicators_.size() && i < context->contexts.size();
i++) {
if (monitor_id >= duplicators_[i].screen_count()) {
monitor_id -= duplicators_[i].screen_count();
} else {
- if (duplicators_[i].DuplicateMonitor(&context->contexts_[i], monitor_id,
+ if (duplicators_[i].DuplicateMonitor(&context->contexts[i], monitor_id,
target)) {
return true;
}
@@ -314,10 +294,23 @@ int64_t DxgiDuplicatorController::GetNumFramesCaptured() const {
return min;
}
-int DxgiDuplicatorController::ScreenCountUnlocked() {
- if (!Initialize()) {
- return 0;
+DesktopSize DxgiDuplicatorController::desktop_size() const {
+ return DesktopSize(desktop_rect_.right(), desktop_rect_.bottom());
+}
+
+DesktopRect DxgiDuplicatorController::ScreenRect(int id) const {
+ RTC_DCHECK(id >= 0);
+ for (size_t i = 0; i < duplicators_.size(); i++) {
+ if (id >= duplicators_[i].screen_count()) {
+ id -= duplicators_[i].screen_count();
+ } else {
+ return duplicators_[i].ScreenRect(id);
+ }
}
+ return DesktopRect();
+}
+
+int DxgiDuplicatorController::ScreenCountUnlocked() const {
int result = 0;
for (auto& duplicator : duplicators_) {
result += duplicator.screen_count();
@@ -325,6 +318,15 @@ int DxgiDuplicatorController::ScreenCountUnlocked() {
return result;
}
+DesktopSize DxgiDuplicatorController::SelectedDesktopSize(
+ int monitor_id) const {
+ if (monitor_id < 0) {
+ return desktop_size();
+ }
+
+ return ScreenRect(monitor_id).size();
+}
+
bool DxgiDuplicatorController::EnsureFrameCaptured(Context* context,
SharedDesktopFrame* target) {
// On a modern system, the FPS / monitor refresh rate is usually larger than
« no previous file with comments | « webrtc/modules/desktop_capture/win/dxgi_duplicator_controller.h ('k') | webrtc/modules/desktop_capture/win/dxgi_frame.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698