diff --git a/modules/desktop_capture/desktop_frame.cc b/modules/desktop_capture/desktop_frame.cc index 030bd8f060..be61196c7d 100644 --- a/modules/desktop_capture/desktop_frame.cc +++ b/modules/desktop_capture/desktop_frame.cc @@ -133,6 +133,7 @@ void DesktopFrame::CopyFrameInfoFrom(const DesktopFrame& other) { *mutable_updated_region() = other.updated_region(); set_top_left(other.top_left()); set_icc_profile(other.icc_profile()); + set_may_contain_cursor(other.may_contain_cursor()); } void DesktopFrame::MoveFrameInfoFrom(DesktopFrame* other) { @@ -142,6 +143,7 @@ void DesktopFrame::MoveFrameInfoFrom(DesktopFrame* other) { mutable_updated_region()->Swap(other->mutable_updated_region()); set_top_left(other->top_left()); set_icc_profile(other->icc_profile()); + set_may_contain_cursor(other->may_contain_cursor()); } bool DesktopFrame::FrameDataIsBlack() const { diff --git a/modules/desktop_capture/screen_capturer_win.cc b/modules/desktop_capture/screen_capturer_win.cc index c535ae86fe..c9bf3a6e98 100644 --- a/modules/desktop_capture/screen_capturer_win.cc +++ b/modules/desktop_capture/screen_capturer_win.cc @@ -24,8 +24,10 @@ namespace webrtc { namespace { -std::unique_ptr CreateScreenCapturerWinDirectx() { - std::unique_ptr capturer(new ScreenCapturerWinDirectx()); +std::unique_ptr CreateScreenCapturerWinDirectx( + const DesktopCaptureOptions& options) { + std::unique_ptr capturer( + new ScreenCapturerWinDirectx(options)); capturer.reset(new BlankDetectorDesktopCapturerWrapper( std::move(capturer), RgbaColor(0, 0, 0, 0))); return capturer; @@ -51,7 +53,7 @@ std::unique_ptr DesktopCapturer::CreateRawScreenCapturer( auto dxgi_duplicator_controller = DxgiDuplicatorController::Instance(); if (ScreenCapturerWinDirectx::IsSupported()) { capturer.reset(new FallbackDesktopCapturerWrapper( - CreateScreenCapturerWinDirectx(), std::move(capturer))); + CreateScreenCapturerWinDirectx(options), std::move(capturer))); return capturer; } } else if (options.allow_use_magnification_api()) { diff --git a/modules/desktop_capture/win/dxgi_output_duplicator.cc b/modules/desktop_capture/win/dxgi_output_duplicator.cc index 599cdacd5b..9c64125b4e 100644 --- a/modules/desktop_capture/win/dxgi_output_duplicator.cc +++ b/modules/desktop_capture/win/dxgi_output_duplicator.cc @@ -147,12 +147,18 @@ bool DxgiOutputDuplicator::ReleaseFrame() { return true; } -void DxgiOutputDuplicator::LogMouseCursor( +bool DxgiOutputDuplicator::ContainsMouseCursor( const DXGI_OUTDUPL_FRAME_INFO& frame_info) { + // The DXGI_OUTDUPL_POINTER_POSITION structure that describes the most recent + // mouse position is only valid if the LastMouseUpdateTime member is a non- + // zero value. + if (frame_info.LastMouseUpdateTime.QuadPart == 0) + return false; + // Ignore cases when the mouse shape has changed and not the position. const bool new_pointer_shape = (frame_info.PointerShapeBufferSize != 0); if (new_pointer_shape) - return; + return false; // The mouse cursor has moved and we can now query if the mouse pointer is // drawn onto the desktop image or not to decide if we must draw the mouse @@ -163,12 +169,10 @@ void DxgiOutputDuplicator::LogMouseCursor( // desktop image, the pointer position data that is reported by // AcquireNextFrame indicates that a separate pointer isn’t visible, hence // `frame_info.PointerPosition.Visible` is false. - // TODO(http://crbug.com/1421656): evaluate this UMA and possibly call - // set_may_contain_cursor(cursor_embedded_in_frame) on the captured frame to - // avoid rendering the cursor twice. const bool cursor_embedded_in_frame = !frame_info.PointerPosition.Visible; RTC_HISTOGRAM_BOOLEAN("WebRTC.DesktopCapture.Win.DirectXCursorEmbedded", cursor_embedded_in_frame); + return cursor_embedded_in_frame; } bool DxgiOutputDuplicator::Duplicate(Context* context, @@ -194,12 +198,7 @@ bool DxgiOutputDuplicator::Duplicate(Context* context, return false; } - // The DXGI_OUTDUPL_POINTER_POSITION structure that describes the most recent - // mouse position is only valid if the LastMouseUpdateTime member is a non- - // zero value. - if (frame_info.LastMouseUpdateTime.QuadPart != 0) { - LogMouseCursor(frame_info); - } + const bool cursor_embedded_in_frame = ContainsMouseCursor(frame_info); // 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 @@ -239,6 +238,7 @@ bool DxgiOutputDuplicator::Duplicate(Context* context, last_frame_offset_ = offset; updated_region.Translate(offset.x(), offset.y()); target->mutable_updated_region()->AddRegion(updated_region); + target->set_may_contain_cursor(cursor_embedded_in_frame); num_frames_captured_++; return texture_->Release() && ReleaseFrame(); } @@ -258,6 +258,7 @@ bool DxgiOutputDuplicator::Duplicate(Context* context, } updated_region.Translate(offset.x(), offset.y()); target->mutable_updated_region()->AddRegion(updated_region); + target->set_may_contain_cursor(cursor_embedded_in_frame); } else { // If we were at the very first frame, and capturing failed, the // context->updated_region should be kept unchanged for next attempt. diff --git a/modules/desktop_capture/win/dxgi_output_duplicator.h b/modules/desktop_capture/win/dxgi_output_duplicator.h index c44c9f2982..a4ce035d8b 100644 --- a/modules/desktop_capture/win/dxgi_output_duplicator.h +++ b/modules/desktop_capture/win/dxgi_output_duplicator.h @@ -97,10 +97,10 @@ class DxgiOutputDuplicator { bool DoDetectUpdatedRegion(const DXGI_OUTDUPL_FRAME_INFO& frame_info, DesktopRegion* updated_region); - // Adds boolean WebRTC.DesktopCapture.Win.DirectXCursorEmbedded UMA stat which - // contains true if the mouse cursor is embedded in the captured frame and - // false if not. - void LogMouseCursor(const DXGI_OUTDUPL_FRAME_INFO& frame_info); + // Returns true if the mouse cursor is embedded in the captured frame and + // false if not. Also logs the same boolean as + // WebRTC.DesktopCapture.Win.DirectXCursorEmbedded UMA. + bool ContainsMouseCursor(const DXGI_OUTDUPL_FRAME_INFO& frame_info); bool ReleaseFrame(); diff --git a/modules/desktop_capture/win/screen_capturer_win_directx.cc b/modules/desktop_capture/win/screen_capturer_win_directx.cc index 3aaac03057..0ed2e12423 100644 --- a/modules/desktop_capture/win/screen_capturer_win_directx.cc +++ b/modules/desktop_capture/win/screen_capturer_win_directx.cc @@ -104,6 +104,12 @@ int ScreenCapturerWinDirectx::GetIndexFromScreenId( ScreenCapturerWinDirectx::ScreenCapturerWinDirectx() : controller_(DxgiDuplicatorController::Instance()) {} +ScreenCapturerWinDirectx::ScreenCapturerWinDirectx( + const DesktopCaptureOptions& options) + : ScreenCapturerWinDirectx() { + options_ = options; +} + ScreenCapturerWinDirectx::~ScreenCapturerWinDirectx() = default; void ScreenCapturerWinDirectx::Start(Callback* callback) { @@ -191,6 +197,12 @@ void ScreenCapturerWinDirectx::CaptureFrame() { capture_time_ms); frame->set_capture_time_ms(capture_time_ms); frame->set_capturer_id(DesktopCapturerId::kScreenCapturerWinDirectx); + // The DXGI Output Duplicator supports embedding the cursor but it is + // only supported on very few display adapters. This switch allows us + // to exclude an integrated cursor for all captured frames. + if (!options_.prefer_cursor_embedded()) { + frame->set_may_contain_cursor(false); + } // TODO(julien.isorce): http://crbug.com/945468. Set the icc profile on // the frame, see WindowCapturerMac::CaptureFrame. diff --git a/modules/desktop_capture/win/screen_capturer_win_directx.h b/modules/desktop_capture/win/screen_capturer_win_directx.h index 801a0632fc..a231643c33 100644 --- a/modules/desktop_capture/win/screen_capturer_win_directx.h +++ b/modules/desktop_capture/win/screen_capturer_win_directx.h @@ -70,7 +70,9 @@ class RTC_EXPORT ScreenCapturerWinDirectx : public DesktopCapturer { static int GetIndexFromScreenId(ScreenId id, const std::vector& device_names); - explicit ScreenCapturerWinDirectx(); + // This constructor is deprecated. Please don't use it in new implementations. + ScreenCapturerWinDirectx(); + explicit ScreenCapturerWinDirectx(const DesktopCaptureOptions& options); ~ScreenCapturerWinDirectx() override; @@ -87,6 +89,7 @@ class RTC_EXPORT ScreenCapturerWinDirectx : public DesktopCapturer { private: const rtc::scoped_refptr controller_; + DesktopCaptureOptions options_; // The underlying DxgiDuplicators may retain a reference to the frames that // we ask them to duplicate so that they can continue returning valid frames