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

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

Issue 2788863006: Merge ScreenCapturerWinDirectx::frames_ and contexts_ (Closed)
Patch Set: Resolve review comments 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
« no previous file with comments | « webrtc/modules/desktop_capture/win/screen_capturer_win_directx.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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" 18 #include "webrtc/base/ptr_util.h"
19 #include "webrtc/base/timeutils.h" 19 #include "webrtc/base/timeutils.h"
20 #include "webrtc/modules/desktop_capture/desktop_frame.h" 20 #include "webrtc/modules/desktop_capture/desktop_frame.h"
21 #include "webrtc/modules/desktop_capture/win/screen_capture_utils.h"
22 21
23 namespace webrtc { 22 namespace webrtc {
24 23
25 using Microsoft::WRL::ComPtr; 24 using Microsoft::WRL::ComPtr;
26 25
27 // static 26 // static
28 bool ScreenCapturerWinDirectx::IsSupported() { 27 bool ScreenCapturerWinDirectx::IsSupported() {
29 // Forwards IsSupported() function call to DxgiDuplicatorController. 28 // Forwards IsSupported() function call to DxgiDuplicatorController.
30 return DxgiDuplicatorController::Instance()->IsSupported(); 29 return DxgiDuplicatorController::Instance()->IsSupported();
31 } 30 }
(...skipping 16 matching lines...) Expand all
48 RTC_DCHECK(callback); 47 RTC_DCHECK(callback);
49 48
50 callback_ = callback; 49 callback_ = callback;
51 } 50 }
52 51
53 void ScreenCapturerWinDirectx::SetSharedMemoryFactory( 52 void ScreenCapturerWinDirectx::SetSharedMemoryFactory(
54 std::unique_ptr<SharedMemoryFactory> shared_memory_factory) { 53 std::unique_ptr<SharedMemoryFactory> shared_memory_factory) {
55 shared_memory_factory_ = std::move(shared_memory_factory); 54 shared_memory_factory_ = std::move(shared_memory_factory);
56 } 55 }
57 56
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() { 57 void ScreenCapturerWinDirectx::CaptureFrame() {
68 RTC_DCHECK(callback_); 58 RTC_DCHECK(callback_);
69 59
70 int64_t capture_start_time_nanos = rtc::TimeNanos(); 60 int64_t capture_start_time_nanos = rtc::TimeNanos();
71 61
72 // The dxgi components and APIs do not update the screen resolution without 62 frames_.MoveToNextFrame();
73 // a reinitialization. So we use the GetDC() function to retrieve the screen 63 if (!frames_.current_frame()) {
74 // resolution to decide whether dxgi components need to be reinitialized. 64 frames_.ReplaceCurrentFrame(
75 // If the screen resolution changed, it's very likely the next Duplicate() 65 rtc::MakeUnique<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 } 66 }
91 67
92 frames_.MoveToNextFrame(); 68 DxgiDuplicatorController::Result result;
93 if (!frames_.current_frame()) { 69 if (current_screen_id_ == kFullDesktopScreenId) {
94 std::unique_ptr<DesktopFrame> new_frame; 70 result = DxgiDuplicatorController::Instance()->Duplicate(
95 if (shared_memory_factory_) { 71 frames_.current_frame());
96 new_frame = SharedMemoryDesktopFrame::Create( 72 } else {
97 SelectedDesktopSize(), shared_memory_factory_.get()); 73 result = DxgiDuplicatorController::Instance()->DuplicateMonitor(
98 } else { 74 frames_.current_frame(), current_screen_id_);
99 new_frame.reset(new BasicDesktopFrame(SelectedDesktopSize())); 75 }
100 } 76
101 if (!new_frame) { 77 using DuplicateResult = DxgiDuplicatorController::Result;
78 switch (result) {
79 case DuplicateResult::FRAME_PREPARE_FAILED: {
102 LOG(LS_ERROR) << "Failed to allocate a new DesktopFrame."; 80 LOG(LS_ERROR) << "Failed to allocate a new DesktopFrame.";
103 // This usually means we do not have enough memory or SharedMemoryFactory 81 // This usually means we do not have enough memory or SharedMemoryFactory
104 // cannot work correctly. 82 // cannot work correctly.
105 callback_->OnCaptureResult(Result::ERROR_PERMANENT, nullptr); 83 callback_->OnCaptureResult(Result::ERROR_PERMANENT, nullptr);
106 return; 84 break;
107 } 85 }
108 frames_.ReplaceCurrentFrame(SharedDesktopFrame::Wrap(std::move(new_frame))); 86 case DuplicateResult::INVALID_MONITOR_ID: {
109 } 87 callback_->OnCaptureResult(Result::ERROR_PERMANENT, nullptr);
110 contexts_.MoveToNextFrame(); 88 break;
111 if (!contexts_.current_frame()) { 89 }
112 contexts_.ReplaceCurrentFrame( 90 case DuplicateResult::INITIALIZATION_FAILED:
113 rtc::MakeUnique<DxgiDuplicatorController::Context>()); 91 case DuplicateResult::DUPLICATION_FAILED: {
114 }
115
116 if (current_screen_id_ == kFullDesktopScreenId) {
117 if (!DxgiDuplicatorController::Instance()->Duplicate(
118 contexts_.current_frame(), frames_.current_frame())) {
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); 92 callback_->OnCaptureResult(Result::ERROR_TEMPORARY, nullptr);
123 return; 93 break;
124 } 94 }
125 } else { 95 case DuplicateResult::SUCCEEDED: {
126 if (!DxgiDuplicatorController::Instance()->DuplicateMonitor( 96 std::unique_ptr<DesktopFrame> frame =
127 contexts_.current_frame(), current_screen_id_, 97 frames_.current_frame()->frame()->Share();
128 frames_.current_frame())) { 98 frame->set_capture_time_ms(
129 // Screen size may be changed, so we need to reset the frames. 99 (rtc::TimeNanos() - capture_start_time_nanos) /
130 frames_.Reset(); 100 rtc::kNumNanosecsPerMillisec);
131 resolution_change_detector_.Reset(); 101 frame->set_capturer_id(DesktopCapturerId::kScreenCapturerWinDirectx);
132 if (current_screen_id_ >= 102 callback_->OnCaptureResult(Result::SUCCESS, std::move(frame));
133 DxgiDuplicatorController::Instance()->ScreenCount()) { 103 break;
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 } 104 }
141 } 105 }
142
143 std::unique_ptr<DesktopFrame> result = frames_.current_frame()->Share();
144 result->set_capture_time_ms(
145 (rtc::TimeNanos() - capture_start_time_nanos) /
146 rtc::kNumNanosecsPerMillisec);
147 result->set_capturer_id(DesktopCapturerId::kScreenCapturerWinDirectx);
148 callback_->OnCaptureResult(Result::SUCCESS, std::move(result));
149 } 106 }
150 107
151 bool ScreenCapturerWinDirectx::GetSourceList(SourceList* sources) { 108 bool ScreenCapturerWinDirectx::GetSourceList(SourceList* sources) {
152 int screen_count = DxgiDuplicatorController::Instance()->ScreenCount(); 109 int screen_count = DxgiDuplicatorController::Instance()->ScreenCount();
153 for (int i = 0; i < screen_count; i++) { 110 for (int i = 0; i < screen_count; i++) {
154 sources->push_back({i}); 111 sources->push_back({i});
155 } 112 }
156 return true; 113 return true;
157 } 114 }
158 115
159 bool ScreenCapturerWinDirectx::SelectSource(SourceId id) { 116 bool ScreenCapturerWinDirectx::SelectSource(SourceId id) {
160 if (id == current_screen_id_) { 117 if (id == current_screen_id_) {
161 return true; 118 return true;
162 } 119 }
163 120
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) { 121 if (id == kFullDesktopScreenId) {
167 current_screen_id_ = id; 122 current_screen_id_ = id;
168 contexts_.Reset();
169 return true; 123 return true;
170 } 124 }
171 125
172 int screen_count = DxgiDuplicatorController::Instance()->ScreenCount(); 126 int screen_count = DxgiDuplicatorController::Instance()->ScreenCount();
173 if (id >= 0 && id < screen_count) { 127 if (id >= 0 && id < screen_count) {
174 current_screen_id_ = id; 128 current_screen_id_ = id;
175 contexts_.Reset();
176 return true; 129 return true;
177 } 130 }
178 return false; 131 return false;
179 } 132 }
180 133
181 } // namespace webrtc 134 } // namespace webrtc
OLDNEW
« no previous file with comments | « webrtc/modules/desktop_capture/win/screen_capturer_win_directx.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698