Index: webrtc/modules/desktop_capture/win/screen_capturer_win_directx.cc |
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 36e43fbad7e47e44452713d66a04e6c80a25e3c8..9630265c63e8720ee3089b9fccb9f1b873aa05e8 100644 |
--- a/webrtc/modules/desktop_capture/win/screen_capturer_win_directx.cc |
+++ b/webrtc/modules/desktop_capture/win/screen_capturer_win_directx.cc |
@@ -18,7 +18,6 @@ |
#include "webrtc/base/ptr_util.h" |
#include "webrtc/base/timeutils.h" |
#include "webrtc/modules/desktop_capture/desktop_frame.h" |
-#include "webrtc/modules/desktop_capture/win/screen_capture_utils.h" |
namespace webrtc { |
@@ -55,97 +54,55 @@ void ScreenCapturerWinDirectx::SetSharedMemoryFactory( |
shared_memory_factory_ = std::move(shared_memory_factory); |
} |
-DesktopSize ScreenCapturerWinDirectx::SelectedDesktopSize() const { |
- if (current_screen_id_ == kFullDesktopScreenId) { |
- return DxgiDuplicatorController::Instance()->desktop_size(); |
- } |
- return DxgiDuplicatorController::Instance() |
- ->ScreenRect(current_screen_id_) |
- .size(); |
-} |
- |
void ScreenCapturerWinDirectx::CaptureFrame() { |
RTC_DCHECK(callback_); |
int64_t capture_start_time_nanos = rtc::TimeNanos(); |
- // 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())) { |
- frames_.Reset(); |
- DxgiDuplicatorController::Instance()->Reset(); |
- resolution_change_detector_.Reset(); |
- } |
- |
frames_.MoveToNextFrame(); |
if (!frames_.current_frame()) { |
- std::unique_ptr<DesktopFrame> new_frame; |
- if (shared_memory_factory_) { |
- new_frame = SharedMemoryDesktopFrame::Create( |
- SelectedDesktopSize(), shared_memory_factory_.get()); |
- } else { |
- new_frame.reset(new BasicDesktopFrame(SelectedDesktopSize())); |
- } |
- if (!new_frame) { |
+ frames_.ReplaceCurrentFrame( |
+ rtc::MakeUnique<DxgiFrame>(shared_memory_factory_.get())); |
+ } |
+ |
+ DxgiDuplicatorController::Result result; |
+ if (current_screen_id_ == kFullDesktopScreenId) { |
+ result = DxgiDuplicatorController::Instance()->Duplicate( |
+ frames_.current_frame()); |
+ } else { |
+ result = DxgiDuplicatorController::Instance()->DuplicateMonitor( |
+ frames_.current_frame(), current_screen_id_); |
+ } |
+ |
+ using DuplicateResult = DxgiDuplicatorController::Result; |
+ switch (result) { |
+ case DuplicateResult::FRAME_PREPARE_FAILED: { |
LOG(LS_ERROR) << "Failed to allocate a new DesktopFrame."; |
// This usually means we do not have enough memory or SharedMemoryFactory |
// cannot work correctly. |
callback_->OnCaptureResult(Result::ERROR_PERMANENT, nullptr); |
- return; |
+ break; |
} |
- frames_.ReplaceCurrentFrame(SharedDesktopFrame::Wrap(std::move(new_frame))); |
- } |
- contexts_.MoveToNextFrame(); |
- if (!contexts_.current_frame()) { |
- contexts_.ReplaceCurrentFrame( |
- rtc::MakeUnique<DxgiDuplicatorController::Context>()); |
- } |
- |
- if (current_screen_id_ == kFullDesktopScreenId) { |
- if (!DxgiDuplicatorController::Instance()->Duplicate( |
- contexts_.current_frame(), frames_.current_frame())) { |
- // Screen size may be changed, so we need to reset the frames. |
- frames_.Reset(); |
- resolution_change_detector_.Reset(); |
+ case DuplicateResult::INVALID_MONITOR_ID: { |
+ callback_->OnCaptureResult(Result::ERROR_PERMANENT, nullptr); |
+ break; |
+ } |
+ case DuplicateResult::INITIALIZATION_FAILED: |
+ case DuplicateResult::DUPLICATION_FAILED: { |
callback_->OnCaptureResult(Result::ERROR_TEMPORARY, nullptr); |
- return; |
+ break; |
} |
- } else { |
- if (!DxgiDuplicatorController::Instance()->DuplicateMonitor( |
- contexts_.current_frame(), current_screen_id_, |
- frames_.current_frame())) { |
- // Screen size may be changed, so we need to reset the frames. |
- frames_.Reset(); |
- resolution_change_detector_.Reset(); |
- if (current_screen_id_ >= |
- DxgiDuplicatorController::Instance()->ScreenCount()) { |
- // Current monitor has been removed from the system. |
- callback_->OnCaptureResult(Result::ERROR_PERMANENT, nullptr); |
- } else { |
- callback_->OnCaptureResult(Result::ERROR_TEMPORARY, nullptr); |
- } |
- return; |
+ case DuplicateResult::SUCCEEDED: { |
+ std::unique_ptr<DesktopFrame> frame = |
+ frames_.current_frame()->frame()->Share(); |
+ frame->set_capture_time_ms( |
+ (rtc::TimeNanos() - capture_start_time_nanos) / |
+ rtc::kNumNanosecsPerMillisec); |
+ frame->set_capturer_id(DesktopCapturerId::kScreenCapturerWinDirectx); |
+ callback_->OnCaptureResult(Result::SUCCESS, std::move(frame)); |
+ break; |
} |
} |
- |
- std::unique_ptr<DesktopFrame> result = frames_.current_frame()->Share(); |
- result->set_capture_time_ms( |
- (rtc::TimeNanos() - capture_start_time_nanos) / |
- rtc::kNumNanosecsPerMillisec); |
- result->set_capturer_id(DesktopCapturerId::kScreenCapturerWinDirectx); |
- callback_->OnCaptureResult(Result::SUCCESS, std::move(result)); |
} |
bool ScreenCapturerWinDirectx::GetSourceList(SourceList* sources) { |
@@ -161,18 +118,14 @@ bool ScreenCapturerWinDirectx::SelectSource(SourceId id) { |
return true; |
} |
- // Changing target screen may or may not impact frame size. So resetting |
- // frames only when a Duplicate() function call returns false. |
if (id == kFullDesktopScreenId) { |
current_screen_id_ = id; |
- contexts_.Reset(); |
return true; |
} |
int screen_count = DxgiDuplicatorController::Instance()->ScreenCount(); |
if (id >= 0 && id < screen_count) { |
current_screen_id_ = id; |
- contexts_.Reset(); |
return true; |
} |
return false; |