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

Side by Side Diff: webrtc/modules/desktop_capture/win/screen_capturer_win_directx.cc

Issue 2788863006: Merge ScreenCapturerWinDirectx::frames_ and contexts_ (Closed)
Patch Set: 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 unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. 2 * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license 4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source 5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found 6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may 7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree. 8 * be found in the AUTHORS file in the root of the source tree.
9 */ 9 */
10 10
11 #include "webrtc/modules/desktop_capture/win/screen_capturer_win_directx.h" 11 #include "webrtc/modules/desktop_capture/win/screen_capturer_win_directx.h"
12 12
13 #include <string> 13 #include <string>
14 #include <utility> 14 #include <utility>
15 15
16 #include "webrtc/base/checks.h" 16 #include "webrtc/base/checks.h"
17 #include "webrtc/base/logging.h" 17 #include "webrtc/base/logging.h"
18 #include "webrtc/base/ptr_util.h"
19 #include "webrtc/base/timeutils.h" 18 #include "webrtc/base/timeutils.h"
20 #include "webrtc/modules/desktop_capture/desktop_frame.h" 19 #include "webrtc/modules/desktop_capture/desktop_frame.h"
21 #include "webrtc/modules/desktop_capture/win/screen_capture_utils.h"
22 20
23 namespace webrtc { 21 namespace webrtc {
24 22
25 using Microsoft::WRL::ComPtr; 23 using Microsoft::WRL::ComPtr;
26 24
27 // static 25 // static
28 bool ScreenCapturerWinDirectx::IsSupported() { 26 bool ScreenCapturerWinDirectx::IsSupported() {
29 // Forwards IsSupported() function call to DxgiDuplicatorController. 27 // Forwards IsSupported() function call to DxgiDuplicatorController.
30 return DxgiDuplicatorController::Instance()->IsSupported(); 28 return DxgiDuplicatorController::Instance()->IsSupported();
31 } 29 }
(...skipping 16 matching lines...) Expand all
48 RTC_DCHECK(callback); 46 RTC_DCHECK(callback);
49 47
50 callback_ = callback; 48 callback_ = callback;
51 } 49 }
52 50
53 void ScreenCapturerWinDirectx::SetSharedMemoryFactory( 51 void ScreenCapturerWinDirectx::SetSharedMemoryFactory(
54 std::unique_ptr<SharedMemoryFactory> shared_memory_factory) { 52 std::unique_ptr<SharedMemoryFactory> shared_memory_factory) {
55 shared_memory_factory_ = std::move(shared_memory_factory); 53 shared_memory_factory_ = std::move(shared_memory_factory);
56 } 54 }
57 55
58 DesktopSize ScreenCapturerWinDirectx::SelectedDesktopSize() const {
59 if (current_screen_id_ == kFullDesktopScreenId) {
60 return DxgiDuplicatorController::Instance()->desktop_size();
61 }
62 return DxgiDuplicatorController::Instance()
63 ->ScreenRect(current_screen_id_)
64 .size();
65 }
66
67 void ScreenCapturerWinDirectx::CaptureFrame() { 56 void ScreenCapturerWinDirectx::CaptureFrame() {
68 RTC_DCHECK(callback_); 57 RTC_DCHECK(callback_);
69 58
70 int64_t capture_start_time_nanos = rtc::TimeNanos(); 59 int64_t capture_start_time_nanos = rtc::TimeNanos();
71 60
72 // The dxgi components and APIs do not update the screen resolution without 61 frames_.MoveToNextFrame();
73 // a reinitialization. So we use the GetDC() function to retrieve the screen 62 if (!frames_.current_frame()) {
74 // resolution to decide whether dxgi components need to be reinitialized. 63 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.
75 // If the screen resolution changed, it's very likely the next Duplicate() 64 new DxgiFrame(shared_memory_factory_.get())));
76 // function call will fail because of a missing monitor or the frame size is
77 // not enough to store the output. So we reinitialize dxgi components in-place
78 // to avoid a capture failure.
79 // But there is no guarantee GetDC() function returns the same resolution as
80 // dxgi APIs, we still rely on dxgi components to return the output frame
81 // size.
82 // TODO(zijiehe): Confirm whether IDXGIOutput::GetDesc() and
83 // IDXGIOutputDuplication::GetDesc() can detect the resolution change without
84 // reinitialization.
85 if (resolution_change_detector_.IsChanged(
86 GetScreenRect(kFullDesktopScreenId, std::wstring()).size())) {
87 frames_.Reset();
88 DxgiDuplicatorController::Instance()->Reset();
89 resolution_change_detector_.Reset();
90 } 65 }
91 66
92 frames_.MoveToNextFrame(); 67 DxgiDuplicatorController::Result result;
93 if (!frames_.current_frame()) { 68 if (current_screen_id_ == kFullDesktopScreenId) {
94 std::unique_ptr<DesktopFrame> new_frame; 69 result = DxgiDuplicatorController::Instance()->Duplicate(
95 if (shared_memory_factory_) { 70 frames_.current_frame());
96 new_frame = SharedMemoryDesktopFrame::Create( 71 } else {
97 SelectedDesktopSize(), shared_memory_factory_.get()); 72 result = DxgiDuplicatorController::Instance()->DuplicateMonitor(
98 } else { 73 frames_.current_frame(), current_screen_id_);
99 new_frame.reset(new BasicDesktopFrame(SelectedDesktopSize()));
100 }
101 if (!new_frame) {
102 LOG(LS_ERROR) << "Failed to allocate a new DesktopFrame.";
103 // This usually means we do not have enough memory or SharedMemoryFactory
104 // cannot work correctly.
105 callback_->OnCaptureResult(Result::ERROR_PERMANENT, nullptr);
106 return;
107 }
108 frames_.ReplaceCurrentFrame(SharedDesktopFrame::Wrap(std::move(new_frame)));
109 }
110 contexts_.MoveToNextFrame();
111 if (!contexts_.current_frame()) {
112 contexts_.ReplaceCurrentFrame(
113 rtc::MakeUnique<DxgiDuplicatorController::Context>());
114 } 74 }
115 75
116 if (current_screen_id_ == kFullDesktopScreenId) { 76 if (result != DxgiDuplicatorController::Result::SUCCEEDED) {
117 if (!DxgiDuplicatorController::Instance()->Duplicate( 77 ProcessDuplicateResult(result);
118 contexts_.current_frame(), frames_.current_frame())) { 78 return;
119 // Screen size may be changed, so we need to reset the frames.
120 frames_.Reset();
121 resolution_change_detector_.Reset();
122 callback_->OnCaptureResult(Result::ERROR_TEMPORARY, nullptr);
123 return;
124 }
125 } else {
126 if (!DxgiDuplicatorController::Instance()->DuplicateMonitor(
127 contexts_.current_frame(), current_screen_id_,
128 frames_.current_frame())) {
129 // Screen size may be changed, so we need to reset the frames.
130 frames_.Reset();
131 resolution_change_detector_.Reset();
132 if (current_screen_id_ >=
133 DxgiDuplicatorController::Instance()->ScreenCount()) {
134 // Current monitor has been removed from the system.
135 callback_->OnCaptureResult(Result::ERROR_PERMANENT, nullptr);
136 } else {
137 callback_->OnCaptureResult(Result::ERROR_TEMPORARY, nullptr);
138 }
139 return;
140 }
141 } 79 }
142 80
143 std::unique_ptr<DesktopFrame> result = frames_.current_frame()->Share(); 81 std::unique_ptr<DesktopFrame> frame =
144 result->set_capture_time_ms( 82 frames_.current_frame()->frame()->Share();
83 frame->set_capture_time_ms(
145 (rtc::TimeNanos() - capture_start_time_nanos) / 84 (rtc::TimeNanos() - capture_start_time_nanos) /
146 rtc::kNumNanosecsPerMillisec); 85 rtc::kNumNanosecsPerMillisec);
147 result->set_capturer_id(DesktopCapturerId::kScreenCapturerWinDirectx); 86 frame->set_capturer_id(DesktopCapturerId::kScreenCapturerWinDirectx);
148 callback_->OnCaptureResult(Result::SUCCESS, std::move(result)); 87 callback_->OnCaptureResult(Result::SUCCESS, std::move(frame));
149 } 88 }
150 89
151 bool ScreenCapturerWinDirectx::GetSourceList(SourceList* sources) { 90 bool ScreenCapturerWinDirectx::GetSourceList(SourceList* sources) {
152 int screen_count = DxgiDuplicatorController::Instance()->ScreenCount(); 91 int screen_count = DxgiDuplicatorController::Instance()->ScreenCount();
153 for (int i = 0; i < screen_count; i++) { 92 for (int i = 0; i < screen_count; i++) {
154 sources->push_back({i}); 93 sources->push_back({i});
155 } 94 }
156 return true; 95 return true;
157 } 96 }
158 97
159 bool ScreenCapturerWinDirectx::SelectSource(SourceId id) { 98 bool ScreenCapturerWinDirectx::SelectSource(SourceId id) {
160 if (id == current_screen_id_) { 99 if (id == current_screen_id_) {
161 return true; 100 return true;
162 } 101 }
163 102
164 // Changing target screen may or may not impact frame size. So resetting
165 // frames only when a Duplicate() function call returns false.
166 if (id == kFullDesktopScreenId) { 103 if (id == kFullDesktopScreenId) {
167 current_screen_id_ = id; 104 current_screen_id_ = id;
168 contexts_.Reset();
169 return true; 105 return true;
170 } 106 }
171 107
172 int screen_count = DxgiDuplicatorController::Instance()->ScreenCount(); 108 int screen_count = DxgiDuplicatorController::Instance()->ScreenCount();
173 if (id >= 0 && id < screen_count) { 109 if (id >= 0 && id < screen_count) {
174 current_screen_id_ = id; 110 current_screen_id_ = id;
175 contexts_.Reset();
176 return true; 111 return true;
177 } 112 }
178 return false; 113 return false;
179 } 114 }
180 115
116 void ScreenCapturerWinDirectx::ProcessDuplicateResult(
117 DxgiDuplicatorController::Result result) {
118 using DuplicateResult = DxgiDuplicatorController::Result;
119 RTC_DCHECK(result != DuplicateResult::SUCCEEDED);
120
121 switch (result) {
122 case DuplicateResult::FRAME_PREPARE_FAILED: {
123 LOG(LS_ERROR) << "Failed to allocate a new DesktopFrame.";
124 // This usually means we do not have enough memory or SharedMemoryFactory
125 // cannot work correctly.
126 callback_->OnCaptureResult(Result::ERROR_PERMANENT, nullptr);
127 break;
128 }
129 case DuplicateResult::INVALID_MONITOR_ID: {
130 callback_->OnCaptureResult(Result::ERROR_PERMANENT, nullptr);
131 break;
132 }
133 case DuplicateResult::INITIALIZATION_FAILED:
134 case DuplicateResult::DUPLICATION_FAILED: {
135 callback_->OnCaptureResult(Result::ERROR_TEMPORARY, nullptr);
136 break;
137 }
138 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.
139 RTC_NOTREACHED();
140 }
141 }
142 }
143
181 } // namespace webrtc 144 } // namespace webrtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698