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

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

Issue 2788863006: Merge ScreenCapturerWinDirectx::frames_ and contexts_ (Closed)
Patch Set: Created 3 years, 9 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..1f65235fef88dc73e50c8b970f0702c232fe33e8 100644
--- a/webrtc/modules/desktop_capture/win/dxgi_duplicator_controller.cc
+++ b/webrtc/modules/desktop_capture/win/dxgi_duplicator_controller.cc
@@ -18,6 +18,7 @@
#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"
@@ -53,11 +54,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 +63,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 +82,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) {
@@ -194,12 +224,14 @@ void DxgiDuplicatorController::Deinitialize() {
bool DxgiDuplicatorController::ContextExpired(
const Context* const context) const {
+ RTC_DCHECK(context);
return context->identity_ != identity_ ||
context->contexts_.size() != duplicators_.size();
}
void DxgiDuplicatorController::Setup(Context* context) {
if (ContextExpired(context)) {
+ RTC_DCHECK(context);
context->contexts_.clear();
context->contexts_.resize(duplicators_.size());
for (size_t i = 0; i < duplicators_.size(); i++) {
@@ -209,51 +241,9 @@ void DxgiDuplicatorController::Setup(Context* context) {
}
}
-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)) {
@@ -314,10 +304,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 +328,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

Powered by Google App Engine
This is Rietveld 408576698