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

Unified Diff: webrtc/modules/desktop_capture/win/screen_capturer_win_directx.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/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..db989ec7e35f50a813d27a2086c1bba2627303f0 100644
--- a/webrtc/modules/desktop_capture/win/screen_capturer_win_directx.cc
+++ b/webrtc/modules/desktop_capture/win/screen_capturer_win_directx.cc
@@ -15,10 +15,8 @@
#include "webrtc/base/checks.h"
#include "webrtc/base/logging.h"
-#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 +53,38 @@ 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) {
- 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;
- }
- frames_.ReplaceCurrentFrame(SharedDesktopFrame::Wrap(std::move(new_frame)));
- }
- contexts_.MoveToNextFrame();
- if (!contexts_.current_frame()) {
- contexts_.ReplaceCurrentFrame(
- rtc::MakeUnique<DxgiDuplicatorController::Context>());
+ frames_.ReplaceCurrentFrame(std::unique_ptr<DxgiFrame>(
Sergey Ulanov 2017/04/18 18:10:16 Please use MakeUnique from base/ptr_util.h
Hzj_jie 2017/04/18 22:17:53 Done.
+ new DxgiFrame(shared_memory_factory_.get())));
}
+ DxgiDuplicatorController::Result result;
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();
- callback_->OnCaptureResult(Result::ERROR_TEMPORARY, nullptr);
- return;
- }
+ result = DxgiDuplicatorController::Instance()->Duplicate(
+ frames_.current_frame());
} 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;
- }
+ result = DxgiDuplicatorController::Instance()->DuplicateMonitor(
+ frames_.current_frame(), current_screen_id_);
}
- std::unique_ptr<DesktopFrame> result = frames_.current_frame()->Share();
- result->set_capture_time_ms(
+ if (result != DxgiDuplicatorController::Result::SUCCEEDED) {
+ ProcessDuplicateResult(result);
+ return;
+ }
+
+ std::unique_ptr<DesktopFrame> frame =
+ frames_.current_frame()->frame()->Share();
+ frame->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));
+ frame->set_capturer_id(DesktopCapturerId::kScreenCapturerWinDirectx);
+ callback_->OnCaptureResult(Result::SUCCESS, std::move(frame));
}
bool ScreenCapturerWinDirectx::GetSourceList(SourceList* sources) {
@@ -161,21 +100,45 @@ 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;
}
+void ScreenCapturerWinDirectx::ProcessDuplicateResult(
+ DxgiDuplicatorController::Result result) {
+ using DuplicateResult = DxgiDuplicatorController::Result;
+ RTC_DCHECK(result != DuplicateResult::SUCCEEDED);
+
+ 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);
+ break;
+ }
+ 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);
+ break;
+ }
+ default: {
Sergey Ulanov 2017/04/18 18:10:16 It's best to avoid default case for switch stateme
Hzj_jie 2017/04/18 22:17:54 Done.
+ RTC_NOTREACHED();
+ }
+ }
+}
+
} // namespace webrtc

Powered by Google App Engine
This is Rietveld 408576698