Index: webrtc/modules/desktop_capture/win/dxgi_output_duplicator.cc |
diff --git a/webrtc/modules/desktop_capture/win/dxgi_output_duplicator.cc b/webrtc/modules/desktop_capture/win/dxgi_output_duplicator.cc |
index 7ce17c66a464e739537fb01202b97e1b92e894b8..00d326768a5395c6cbcf9ff5c642c8647e935e4d 100644 |
--- a/webrtc/modules/desktop_capture/win/dxgi_output_duplicator.cc |
+++ b/webrtc/modules/desktop_capture/win/dxgi_output_duplicator.cc |
@@ -118,12 +118,17 @@ bool DxgiOutputDuplicator::ReleaseFrame() { |
} |
bool DxgiOutputDuplicator::Duplicate(Context* context, |
- const DesktopFrame* last_frame, |
const DesktopVector offset, |
- DesktopFrame* target) { |
+ SharedDesktopFrame* target) { |
RTC_DCHECK(duplication_); |
RTC_DCHECK(texture_); |
RTC_DCHECK(target); |
+ if (!DesktopRect::MakeSize(target->size()) |
+ .ContainsRect(TranslatedDesktopRect(offset))) { |
+ // target size is not large enough to cover current output region. |
+ return false; |
+ } |
+ |
DXGI_OUTDUPL_FRAME_INFO frame_info; |
memset(&frame_info, 0, sizeof(frame_info)); |
ComPtr<IDXGIResource> resource; |
@@ -140,40 +145,35 @@ bool DxgiOutputDuplicator::Duplicate(Context* context, |
// buffering implementation, as what we have in ScreenCapturerWinDirectx. If |
// a consumer uses single buffering, we should clear context->updated_region |
// after it has been merged to updated_region. |
- DesktopRegion updated_region = context->updated_region; |
+ DesktopRegion updated_region; |
+ updated_region.Swap(&context->updated_region); |
if (error.Error() == S_OK && frame_info.AccumulatedFrames > 0) { |
DetectUpdatedRegion(frame_info, offset, &context->updated_region); |
- SpreadContextChange(context); |
- updated_region.AddRegion(context->updated_region); |
- if (!texture_->CopyFrom(frame_info, resource.Get(), updated_region)) { |
+ if (!texture_->CopyFrom(frame_info, resource.Get(), |
+ context->updated_region)) { |
return false; |
} |
- |
+ SpreadContextChange(context); |
+ updated_region.AddRegion(context->updated_region); |
const DesktopFrame& source = texture_->AsDesktopFrame(); |
- DesktopRect target_rect(DesktopRect::MakeSize(target->size())); |
for (DesktopRegion::Iterator it(updated_region); !it.IsAtEnd(); |
it.Advance()) { |
- if (!target_rect.ContainsRect(it.rect())) { |
- // target size is not large enough to copy the pixel from texture. |
- return false; |
- } |
target->CopyPixelsFrom(source, it.rect().top_left().subtract(offset), |
it.rect()); |
} |
+ last_frame_ = target->Share(); |
+ last_frame_offset_ = offset; |
target->mutable_updated_region()->AddRegion(updated_region); |
return texture_->Release() && ReleaseFrame(); |
} |
- if (last_frame != nullptr) { |
- // DxgiOutputDuplicatorContainer::Duplicate() makes sure target size and |
- // last frame size are consistent. |
- RTC_DCHECK(target->size().equals(last_frame->size())); |
+ if (last_frame_) { |
// No change since last frame or AcquireNextFrame() timed out, we will |
// export last frame to the target. |
context->updated_region.Clear(); |
for (DesktopRegion::Iterator it(updated_region); !it.IsAtEnd(); |
it.Advance()) { |
- target->CopyPixelsFrom(*last_frame, it.rect().top_left(), it.rect()); |
+ target->CopyPixelsFrom(*last_frame_, last_frame_offset_, it.rect()); |
} |
target->mutable_updated_region()->AddRegion(updated_region); |
} |