| 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 04f466455fe11aa525c487e0d97ae38e6283d91b..fb8dacb720a34b55f051e999463c8f2091d27f5b 100644
|
| --- a/webrtc/modules/desktop_capture/win/dxgi_output_duplicator.cc
|
| +++ b/webrtc/modules/desktop_capture/win/dxgi_output_duplicator.cc
|
| @@ -57,12 +57,6 @@ Rotation DxgiRotationToRotation(DXGI_MODE_ROTATION rotation) {
|
| return Rotation::CLOCK_WISE_0;
|
| }
|
|
|
| -// Translates |rect| with the reverse of |offset|
|
| -DesktopRect ReverseTranslate(DesktopRect rect, DesktopVector offset) {
|
| - rect.Translate(-offset.x(), -offset.y());
|
| - return rect;
|
| -}
|
| -
|
| } // namespace
|
|
|
| DxgiOutputDuplicator::DxgiOutputDuplicator(const D3dDevice& device,
|
| @@ -132,8 +126,7 @@ bool DxgiOutputDuplicator::DuplicateOutput() {
|
| }
|
|
|
| rotation_ = DxgiRotationToRotation(desc_.Rotation);
|
| - unrotated_size_ =
|
| - RotateSize(desktop_rect_.size(), ReverseRotation(rotation_));
|
| + unrotated_size_ = RotateSize(desktop_size(), ReverseRotation(rotation_));
|
|
|
| return true;
|
| }
|
| @@ -157,7 +150,7 @@ bool DxgiOutputDuplicator::Duplicate(Context* context,
|
| RTC_DCHECK(texture_);
|
| RTC_DCHECK(target);
|
| if (!DesktopRect::MakeSize(target->size())
|
| - .ContainsRect(TranslatedDesktopRect(offset))) {
|
| + .ContainsRect(GetTranslatedDesktopRect(offset))) {
|
| // target size is not large enough to cover current output region.
|
| return false;
|
| }
|
| @@ -175,37 +168,43 @@ bool DxgiOutputDuplicator::Duplicate(Context* context,
|
|
|
| // We need to merge updated region with the one from context, but only spread
|
| // updated region from current frame. So keeps a copy of updated region from
|
| - // context here.
|
| + // context here. The |updated_region| always starts from (0, 0).
|
| DesktopRegion updated_region;
|
| updated_region.Swap(&context->updated_region);
|
| if (error.Error() == S_OK &&
|
| frame_info.AccumulatedFrames > 0 &&
|
| resource) {
|
| - DetectUpdatedRegion(frame_info, offset, &context->updated_region);
|
| + DetectUpdatedRegion(frame_info, &context->updated_region);
|
| + SpreadContextChange(context);
|
| if (!texture_->CopyFrom(frame_info, resource.Get())) {
|
| return false;
|
| }
|
| - SpreadContextChange(context);
|
| updated_region.AddRegion(context->updated_region);
|
| + // TODO(zijiehe): Figure out why clearing context->updated_region() here
|
| + // triggers screen flickering?
|
|
|
| const DesktopFrame& source = texture_->AsDesktopFrame();
|
| if (rotation_ != Rotation::CLOCK_WISE_0) {
|
| for (DesktopRegion::Iterator it(updated_region); !it.IsAtEnd();
|
| it.Advance()) {
|
| - const DesktopRect source_rect =
|
| - RotateRect(ReverseTranslate(it.rect(), offset),
|
| - desktop_rect().size(), ReverseRotation(rotation_));
|
| + // The |updated_region| returned by Windows is rotated, but the |source|
|
| + // frame is not. So we need to rotate it reversely.
|
| + const DesktopRect source_rect = RotateRect(
|
| + it.rect(), desktop_size(), ReverseRotation(rotation_));
|
| RotateDesktopFrame(source, source_rect, rotation_, offset, target);
|
| }
|
| } else {
|
| for (DesktopRegion::Iterator it(updated_region); !it.IsAtEnd();
|
| it.Advance()) {
|
| - target->CopyPixelsFrom(
|
| - source, ReverseTranslate(it.rect(), offset).top_left(), it.rect());
|
| + // The DesktopRect in |target|, starts from offset.
|
| + DesktopRect dest_rect = it.rect();
|
| + dest_rect.Translate(offset);
|
| + target->CopyPixelsFrom(source, it.rect().top_left(), dest_rect);
|
| }
|
| }
|
| last_frame_ = target->Share();
|
| last_frame_offset_ = offset;
|
| + updated_region.Translate(offset.x(), offset.y());
|
| target->mutable_updated_region()->AddRegion(updated_region);
|
| num_frames_captured_++;
|
| return texture_->Release() && ReleaseFrame();
|
| @@ -216,8 +215,15 @@ bool DxgiOutputDuplicator::Duplicate(Context* context,
|
| // export last frame to the target.
|
| for (DesktopRegion::Iterator it(updated_region); !it.IsAtEnd();
|
| it.Advance()) {
|
| - target->CopyPixelsFrom(*last_frame_, it.rect().top_left(), it.rect());
|
| + // The DesktopRect in |source|, starts from last_frame_offset_.
|
| + DesktopRect source_rect = it.rect();
|
| + // The DesktopRect in |target|, starts from offset.
|
| + DesktopRect target_rect = source_rect;
|
| + source_rect.Translate(last_frame_offset_);
|
| + target_rect.Translate(offset);
|
| + target->CopyPixelsFrom(*last_frame_, source_rect.top_left(), target_rect);
|
| }
|
| + updated_region.Translate(offset.x(), offset.y());
|
| target->mutable_updated_region()->AddRegion(updated_region);
|
| } else {
|
| // If we were at the very first frame, and capturing failed, the
|
| @@ -229,23 +235,26 @@ bool DxgiOutputDuplicator::Duplicate(Context* context,
|
| return error.Error() == DXGI_ERROR_WAIT_TIMEOUT || ReleaseFrame();
|
| }
|
|
|
| -DesktopRect DxgiOutputDuplicator::TranslatedDesktopRect(DesktopVector offset) {
|
| - DesktopRect result(DesktopRect::MakeSize(desktop_rect_.size()));
|
| +DesktopRect DxgiOutputDuplicator::GetTranslatedDesktopRect(
|
| + DesktopVector offset) const {
|
| + DesktopRect result(DesktopRect::MakeSize(desktop_size()));
|
| result.Translate(offset);
|
| return result;
|
| }
|
|
|
| +DesktopRect DxgiOutputDuplicator::GetUntranslatedDesktopRect() const {
|
| + return DesktopRect::MakeSize(desktop_size());
|
| +}
|
| +
|
| void DxgiOutputDuplicator::DetectUpdatedRegion(
|
| const DXGI_OUTDUPL_FRAME_INFO& frame_info,
|
| - DesktopVector offset,
|
| DesktopRegion* updated_region) {
|
| if (DoDetectUpdatedRegion(frame_info, updated_region)) {
|
| - updated_region->Translate(offset.x(), offset.y());
|
| // Make sure even a region returned by Windows API is out of the scope of
|
| // desktop_rect_, we still won't export it to the target DesktopFrame.
|
| - updated_region->IntersectWith(TranslatedDesktopRect(offset));
|
| + updated_region->IntersectWith(GetUntranslatedDesktopRect());
|
| } else {
|
| - updated_region->SetRect(TranslatedDesktopRect(offset));
|
| + updated_region->SetRect(GetUntranslatedDesktopRect());
|
| }
|
| }
|
|
|
| @@ -340,7 +349,7 @@ bool DxgiOutputDuplicator::DoDetectUpdatedRegion(
|
| void DxgiOutputDuplicator::Setup(Context* context) {
|
| RTC_DCHECK(context->updated_region.is_empty());
|
| // Always copy entire monitor during the first Duplicate() function call.
|
| - context->updated_region.AddRect(desktop_rect_);
|
| + context->updated_region.AddRect(GetUntranslatedDesktopRect());
|
| RTC_DCHECK(std::find(contexts_.begin(), contexts_.end(), context) ==
|
| contexts_.end());
|
| contexts_.push_back(context);
|
| @@ -361,6 +370,10 @@ void DxgiOutputDuplicator::SpreadContextChange(const Context* const source) {
|
| }
|
| }
|
|
|
| +DesktopSize DxgiOutputDuplicator::desktop_size() const {
|
| + return desktop_rect_.size();
|
| +}
|
| +
|
| int64_t DxgiOutputDuplicator::num_frames_captured() const {
|
| #if !defined(NDEBUG)
|
| RTC_DCHECK_EQ(!!last_frame_, num_frames_captured_ > 0);
|
|
|