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

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

Issue 2299663003: [WebRTC] Two DirectX capturers cannot work concurrently (Closed)
Patch Set: Created 4 years, 3 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
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
111 if (error.Error() != S_OK) { 111 if (error.Error() != S_OK) {
112 LOG(LS_ERROR) << "Failed to release frame from IDXGIOutputDuplication, " 112 LOG(LS_ERROR) << "Failed to release frame from IDXGIOutputDuplication, "
113 "error" 113 "error"
114 << error.ErrorMessage() << ", code " << error.Error(); 114 << error.ErrorMessage() << ", code " << error.Error();
115 return false; 115 return false;
116 } 116 }
117 return true; 117 return true;
118 } 118 }
119 119
120 bool DxgiOutputDuplicator::Duplicate(Context* context, 120 bool DxgiOutputDuplicator::Duplicate(Context* context,
121 const DesktopFrame* last_frame, 121 const DesktopVector& offset,
122 const DesktopVector offset, 122 SharedDesktopFrame* target) {
123 DesktopFrame* target) {
124 RTC_DCHECK(duplication_); 123 RTC_DCHECK(duplication_);
125 RTC_DCHECK(texture_); 124 RTC_DCHECK(texture_);
126 RTC_DCHECK(target); 125 RTC_DCHECK(target);
126 if (!DesktopRect::MakeSize(target->size())
127 .ContainsRect(TranslatedDesktopRect(offset))) {
128 // target size is not large enough to cover current output region.
129 return false;
130 }
131
127 DXGI_OUTDUPL_FRAME_INFO frame_info; 132 DXGI_OUTDUPL_FRAME_INFO frame_info;
128 memset(&frame_info, 0, sizeof(frame_info)); 133 memset(&frame_info, 0, sizeof(frame_info));
129 ComPtr<IDXGIResource> resource; 134 ComPtr<IDXGIResource> resource;
130 _com_error error = duplication_->AcquireNextFrame( 135 _com_error error = duplication_->AcquireNextFrame(
131 kAcquireTimeoutMs, &frame_info, resource.GetAddressOf()); 136 kAcquireTimeoutMs, &frame_info, resource.GetAddressOf());
132 if (error.Error() != S_OK && error.Error() != DXGI_ERROR_WAIT_TIMEOUT) { 137 if (error.Error() != S_OK && error.Error() != DXGI_ERROR_WAIT_TIMEOUT) {
133 LOG(LS_ERROR) << "Failed to capture frame, error " << error.ErrorMessage() 138 LOG(LS_ERROR) << "Failed to capture frame, error " << error.ErrorMessage()
134 << ", code " << error.Error(); 139 << ", code " << error.Error();
135 return false; 140 return false;
136 } 141 }
137 142
138 // We need to merge updated region with the one from last frame, since current 143 // We need to merge updated region with the one from last frame, since current
139 // frame contains the content one frame before. Note, this is for double 144 // frame contains the content one frame before. Note, this is for double
140 // buffering implementation, as what we have in ScreenCapturerWinDirectx. If 145 // buffering implementation, as what we have in ScreenCapturerWinDirectx. If
141 // a consumer uses single buffering, we should clear context->updated_region 146 // a consumer uses single buffering, we should clear context->updated_region
142 // after it has been merged to updated_region. 147 // after it has been merged to updated_region.
143 DesktopRegion updated_region = context->updated_region; 148 DesktopRegion updated_region;
149 updated_region.Swap(&context->updated_region);
144 if (error.Error() == S_OK && frame_info.AccumulatedFrames > 0) { 150 if (error.Error() == S_OK && frame_info.AccumulatedFrames > 0) {
145 DetectUpdatedRegion(frame_info, offset, &context->updated_region); 151 DetectUpdatedRegion(frame_info, offset, &context->updated_region);
152 if (!texture_->CopyFrom(frame_info, resource.Get(),
153 context->updated_region)) {
154 return false;
155 }
146 SpreadContextChange(context); 156 SpreadContextChange(context);
147 updated_region.AddRegion(context->updated_region); 157 updated_region.AddRegion(context->updated_region);
148 if (!texture_->CopyFrom(frame_info, resource.Get(), updated_region)) {
149 return false;
150 }
151 158
152 const DesktopFrame& source = texture_->AsDesktopFrame(); 159 const DesktopFrame& source = texture_->AsDesktopFrame();
153 DesktopRect target_rect(DesktopRect::MakeSize(target->size()));
154 for (DesktopRegion::Iterator it(updated_region); !it.IsAtEnd(); 160 for (DesktopRegion::Iterator it(updated_region); !it.IsAtEnd();
155 it.Advance()) { 161 it.Advance()) {
156 if (!target_rect.ContainsRect(it.rect())) { 162 target->CopyPixelsFrom(source, SourceRect(it.rect()).top_left(),
157 // target size is not large enough to copy the pixel from texture. 163 TargetRect(it.rect(), offset));
158 return false;
159 }
160 target->CopyPixelsFrom(source, it.rect().top_left().subtract(offset),
161 it.rect());
162 } 164 }
165 last_frame_ = target->Share();
166 last_frame_offset_ = offset;
163 target->mutable_updated_region()->AddRegion(updated_region); 167 target->mutable_updated_region()->AddRegion(updated_region);
164 return texture_->Release() && ReleaseFrame(); 168 return texture_->Release() && ReleaseFrame();
165 } 169 }
166 170
167 if (last_frame != nullptr) { 171 if (last_frame_) {
168 // DxgiOutputDuplicatorContainer::Duplicate() makes sure target size and
169 // last frame size are consistent.
170 RTC_DCHECK(target->size().equals(last_frame->size()));
171 // No change since last frame or AcquireNextFrame() timed out, we will 172 // No change since last frame or AcquireNextFrame() timed out, we will
172 // export last frame to the target. 173 // export last frame to the target.
173 context->updated_region.Clear(); 174 context->updated_region.Clear();
Sergey Ulanov 2016/09/02 23:57:35 Don't need this anymore
Hzj_jie 2016/09/05 21:24:22 Done.
174 for (DesktopRegion::Iterator it(updated_region); !it.IsAtEnd(); 175 for (DesktopRegion::Iterator it(updated_region); !it.IsAtEnd();
Sergey Ulanov 2016/09/02 23:57:35 This duplicates the code that you have above in li
Hzj_jie 2016/09/05 21:24:22 The code between 160 - 168 copies from texture_->A
175 it.Advance()) { 176 it.Advance()) {
176 target->CopyPixelsFrom(*last_frame, it.rect().top_left(), it.rect()); 177 target->CopyPixelsFrom(*last_frame_, SourceRect(it.rect()).top_left(),
178 TargetRect(it.rect(), offset));
177 } 179 }
178 target->mutable_updated_region()->AddRegion(updated_region); 180 target->mutable_updated_region()->AddRegion(updated_region);
179 } 181 }
180 // If AcquireNextFrame() failed with timeout error, we do not need to release 182 // If AcquireNextFrame() failed with timeout error, we do not need to release
181 // the frame. 183 // the frame.
182 return error.Error() == DXGI_ERROR_WAIT_TIMEOUT || ReleaseFrame(); 184 return error.Error() == DXGI_ERROR_WAIT_TIMEOUT || ReleaseFrame();
183 } 185 }
184 186
185 DesktopRect DxgiOutputDuplicator::TranslatedDesktopRect( 187 DesktopRect DxgiOutputDuplicator::TranslatedDesktopRect(
186 const DesktopVector offset) { 188 const DesktopVector& offset) {
187 DesktopRect result(DesktopRect::MakeSize(desktop_rect_.size())); 189 DesktopRect result(DesktopRect::MakeSize(desktop_rect_.size()));
188 result.Translate(offset); 190 result.Translate(offset);
189 return result; 191 return result;
190 } 192 }
191 193
192 void DxgiOutputDuplicator::DetectUpdatedRegion( 194 void DxgiOutputDuplicator::DetectUpdatedRegion(
193 const DXGI_OUTDUPL_FRAME_INFO& frame_info, 195 const DXGI_OUTDUPL_FRAME_INFO& frame_info,
194 const DesktopVector offset, 196 const DesktopVector& offset,
195 DesktopRegion* updated_region) { 197 DesktopRegion* updated_region) {
196 if (DoDetectUpdatedRegion(frame_info, updated_region)) { 198 if (DoDetectUpdatedRegion(frame_info, updated_region)) {
197 updated_region->Translate(offset.x(), offset.y()); 199 updated_region->Translate(offset.x(), offset.y());
198 // Make sure even a region returned by Windows API is out of the scope of 200 // Make sure even a region returned by Windows API is out of the scope of
199 // desktop_rect_, we still won't export it to the target DesktopFrame. 201 // desktop_rect_, we still won't export it to the target DesktopFrame.
200 updated_region->IntersectWith(TranslatedDesktopRect(offset)); 202 updated_region->IntersectWith(TranslatedDesktopRect(offset));
201 } else { 203 } else {
202 updated_region->SetRect(TranslatedDesktopRect(offset)); 204 updated_region->SetRect(TranslatedDesktopRect(offset));
203 } 205 }
204 } 206 }
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
294 } 296 }
295 297
296 void DxgiOutputDuplicator::SpreadContextChange(const Context* const source) { 298 void DxgiOutputDuplicator::SpreadContextChange(const Context* const source) {
297 for (Context* dest : contexts_) { 299 for (Context* dest : contexts_) {
298 if (dest != source) { 300 if (dest != source) {
299 dest->updated_region.AddRegion(source->updated_region); 301 dest->updated_region.AddRegion(source->updated_region);
300 } 302 }
301 } 303 }
302 } 304 }
303 305
306 DesktopRect DxgiOutputDuplicator::SourceRect(DesktopRect rect) {
307 // |texture_|->AsDesktopFrame() starts from (0, 0).
308 rect.Translate(-desktop_rect_.left(), -desktop_rect_.top());
309 return rect;
310 }
311
312 DesktopRect DxgiOutputDuplicator::TargetRect(DesktopRect rect,
313 DesktopVector offset) {
314 rect = SourceRect(rect);
315 rect.Translate(offset);
316 return rect;
317 }
318
304 } // namespace webrtc 319 } // namespace webrtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698