mirror of
https://github.com/mollyim/webrtc.git
synced 2025-05-12 21:30:45 +01:00
DXGI now consumes may_contain_cursor
Before: No attempt was made to figure out of the cursor was embedded into the captured video frame when using DXGI on Windows as screen capturer. Instead the cursor is superimposed on the frame by an external mouse and cursor composer. After: We now check if the display adapter supports embedding the mouse cursor and if so use it as is and thereby avoid adding it independently. Bug: chromium:1421656 Change-Id: Ie07fe13e1c8f9583769961328bb41fbc689cd8e0 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/299241 Reviewed-by: Alexander Cooper <alcooper@chromium.org> Commit-Queue: Henrik Andreassson <henrika@webrtc.org> Cr-Commit-Position: refs/heads/main@{#39742}
This commit is contained in:
parent
a0e4ce0e81
commit
d549e4b6ce
6 changed files with 39 additions and 19 deletions
|
@ -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 {
|
||||
|
|
|
@ -24,8 +24,10 @@ namespace webrtc {
|
|||
|
||||
namespace {
|
||||
|
||||
std::unique_ptr<DesktopCapturer> CreateScreenCapturerWinDirectx() {
|
||||
std::unique_ptr<DesktopCapturer> capturer(new ScreenCapturerWinDirectx());
|
||||
std::unique_ptr<DesktopCapturer> CreateScreenCapturerWinDirectx(
|
||||
const DesktopCaptureOptions& options) {
|
||||
std::unique_ptr<DesktopCapturer> 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> 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()) {
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -70,7 +70,9 @@ class RTC_EXPORT ScreenCapturerWinDirectx : public DesktopCapturer {
|
|||
static int GetIndexFromScreenId(ScreenId id,
|
||||
const std::vector<std::string>& 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<DxgiDuplicatorController> 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
|
||||
|
|
Loading…
Reference in a new issue