| 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;
|
|
|