| 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 9c0f14c43d2a8a1552d9c0c619a81a0ef7c2b218..9e35b6cdc5df5cbfcbafbff3f04ccaa56df33d1e 100644
|
| --- a/webrtc/modules/desktop_capture/win/dxgi_output_duplicator.cc
|
| +++ b/webrtc/modules/desktop_capture/win/dxgi_output_duplicator.cc
|
| @@ -13,6 +13,7 @@
|
| #include <string.h>
|
|
|
| #include <unknwn.h>
|
| +#include <DXGI.h>
|
| #include <DXGIFormat.h>
|
| #include <Windows.h>
|
|
|
| @@ -36,6 +37,29 @@ DesktopRect RECTToDesktopRect(const RECT& rect) {
|
| return DesktopRect::MakeLTRB(rect.left, rect.top, rect.right, rect.bottom);
|
| }
|
|
|
| +Rotation DxgiRotationToRotation(DXGI_MODE_ROTATION rotation) {
|
| + switch (rotation) {
|
| + case DXGI_MODE_ROTATION_IDENTITY:
|
| + case DXGI_MODE_ROTATION_UNSPECIFIED:
|
| + return Rotation::CLOCK_WISE_0;
|
| + case DXGI_MODE_ROTATION_ROTATE90:
|
| + return Rotation::CLOCK_WISE_90;
|
| + case DXGI_MODE_ROTATION_ROTATE180:
|
| + return Rotation::CLOCK_WISE_180;
|
| + case DXGI_MODE_ROTATION_ROTATE270:
|
| + return Rotation::CLOCK_WISE_270;
|
| + }
|
| +
|
| + RTC_NOTREACHED();
|
| + 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,
|
| @@ -61,10 +85,13 @@ DxgiOutputDuplicator::~DxgiOutputDuplicator() {
|
|
|
| bool DxgiOutputDuplicator::Initialize() {
|
| if (DuplicateOutput()) {
|
| + DesktopSize unrotated_size =
|
| + RotateSize(desktop_rect().size(), ReverseRotation(rotation_));
|
| if (desc_.DesktopImageInSystemMemory) {
|
| - texture_.reset(new DxgiTextureMapping(desktop_rect_, duplication_.Get()));
|
| + texture_.reset(
|
| + new DxgiTextureMapping(unrotated_size, duplication_.Get()));
|
| } else {
|
| - texture_.reset(new DxgiTextureStaging(desktop_rect_, device_));
|
| + texture_.reset(new DxgiTextureStaging(unrotated_size, device_));
|
| }
|
| return true;
|
| } else {
|
| @@ -104,6 +131,10 @@ bool DxgiOutputDuplicator::DuplicateOutput() {
|
| return false;
|
| }
|
|
|
| + rotation_ = DxgiRotationToRotation(desc_.Rotation);
|
| + unrotated_size_ =
|
| + RotateSize(desktop_rect_.size(), ReverseRotation(rotation_));
|
| +
|
| return true;
|
| }
|
|
|
| @@ -142,29 +173,36 @@ bool DxgiOutputDuplicator::Duplicate(Context* context,
|
| return false;
|
| }
|
|
|
| - // We need to merge updated region with the one from last frame, since current
|
| - // frame contains the content one frame before. Note, this is for double
|
| - // 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.
|
| + // 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.
|
| 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);
|
| - if (!texture_->CopyFrom(frame_info, resource.Get(),
|
| - context->updated_region)) {
|
| + if (!texture_->CopyFrom(frame_info, resource.Get())) {
|
| return false;
|
| }
|
| SpreadContextChange(context);
|
| updated_region.AddRegion(context->updated_region);
|
|
|
| const DesktopFrame& source = texture_->AsDesktopFrame();
|
| - for (DesktopRegion::Iterator it(updated_region); !it.IsAtEnd();
|
| - it.Advance()) {
|
| - target->CopyPixelsFrom(
|
| - source, SourceRect(it.rect()).top_left(), it.rect());
|
| + 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_));
|
| + 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());
|
| + }
|
| }
|
| last_frame_ = target->Share();
|
| last_frame_offset_ = offset;
|
| @@ -218,17 +256,17 @@ bool DxgiOutputDuplicator::DoDetectUpdatedRegion(
|
| return false;
|
| }
|
|
|
| - if (metadata.capacity() < frame_info.TotalMetadataBufferSize) {
|
| - metadata.clear(); // Avoid data copy
|
| - metadata.reserve(frame_info.TotalMetadataBufferSize);
|
| + if (metadata_.capacity() < frame_info.TotalMetadataBufferSize) {
|
| + metadata_.clear(); // Avoid data copy
|
| + metadata_.reserve(frame_info.TotalMetadataBufferSize);
|
| }
|
|
|
| UINT buff_size = 0;
|
| DXGI_OUTDUPL_MOVE_RECT* move_rects =
|
| - reinterpret_cast<DXGI_OUTDUPL_MOVE_RECT*>(metadata.data());
|
| + reinterpret_cast<DXGI_OUTDUPL_MOVE_RECT*>(metadata_.data());
|
| size_t move_rects_count = 0;
|
| _com_error error = duplication_->GetFrameMoveRects(
|
| - static_cast<UINT>(metadata.capacity()), move_rects, &buff_size);
|
| + static_cast<UINT>(metadata_.capacity()), move_rects, &buff_size);
|
| if (error.Error() != S_OK) {
|
| LOG(LS_ERROR) << "Failed to get move rectangles, error "
|
| << error.ErrorMessage() << ", code " << error.Error();
|
| @@ -236,10 +274,10 @@ bool DxgiOutputDuplicator::DoDetectUpdatedRegion(
|
| }
|
| move_rects_count = buff_size / sizeof(DXGI_OUTDUPL_MOVE_RECT);
|
|
|
| - RECT* dirty_rects = reinterpret_cast<RECT*>(metadata.data() + buff_size);
|
| + RECT* dirty_rects = reinterpret_cast<RECT*>(metadata_.data() + buff_size);
|
| size_t dirty_rects_count = 0;
|
| error = duplication_->GetFrameDirtyRects(
|
| - static_cast<UINT>(metadata.capacity()) - buff_size, dirty_rects,
|
| + static_cast<UINT>(metadata_.capacity()) - buff_size, dirty_rects,
|
| &buff_size);
|
| if (error.Error() != S_OK) {
|
| LOG(LS_ERROR) << "Failed to get dirty rectangles, error "
|
| @@ -249,21 +287,29 @@ bool DxgiOutputDuplicator::DoDetectUpdatedRegion(
|
| dirty_rects_count = buff_size / sizeof(RECT);
|
|
|
| while (move_rects_count > 0) {
|
| - updated_region->AddRect(DesktopRect::MakeXYWH(
|
| - move_rects->SourcePoint.x, move_rects->SourcePoint.y,
|
| - move_rects->DestinationRect.right - move_rects->DestinationRect.left,
|
| - move_rects->DestinationRect.bottom - move_rects->DestinationRect.top));
|
| - updated_region->AddRect(DesktopRect::MakeLTRB(
|
| - move_rects->DestinationRect.left, move_rects->DestinationRect.top,
|
| - move_rects->DestinationRect.right, move_rects->DestinationRect.bottom));
|
| + updated_region->AddRect(
|
| + RotateRect(DesktopRect::MakeXYWH(move_rects->SourcePoint.x,
|
| + move_rects->SourcePoint.y,
|
| + move_rects->DestinationRect.right -
|
| + move_rects->DestinationRect.left,
|
| + move_rects->DestinationRect.bottom -
|
| + move_rects->DestinationRect.top),
|
| + unrotated_size_, rotation_));
|
| + updated_region->AddRect(
|
| + RotateRect(DesktopRect::MakeLTRB(move_rects->DestinationRect.left,
|
| + move_rects->DestinationRect.top,
|
| + move_rects->DestinationRect.right,
|
| + move_rects->DestinationRect.bottom),
|
| + unrotated_size_, rotation_));
|
| move_rects++;
|
| move_rects_count--;
|
| }
|
|
|
| while (dirty_rects_count > 0) {
|
| - updated_region->AddRect(
|
| + updated_region->AddRect(RotateRect(
|
| DesktopRect::MakeLTRB(dirty_rects->left, dirty_rects->top,
|
| - dirty_rects->right, dirty_rects->bottom));
|
| + dirty_rects->right, dirty_rects->bottom),
|
| + unrotated_size_, rotation_));
|
| dirty_rects++;
|
| dirty_rects_count--;
|
| }
|
| @@ -295,10 +341,4 @@ void DxgiOutputDuplicator::SpreadContextChange(const Context* const source) {
|
| }
|
| }
|
|
|
| -DesktopRect DxgiOutputDuplicator::SourceRect(DesktopRect rect) {
|
| - // |texture_|->AsDesktopFrame() starts from (0, 0).
|
| - rect.Translate(-desktop_rect_.left(), -desktop_rect_.top());
|
| - return rect;
|
| -}
|
| -
|
| } // namespace webrtc
|
|
|