From 9a2c408a1a240e9aa16b548a3c17281c572f37fc Mon Sep 17 00:00:00 2001 From: Palak Agarwal Date: Tue, 18 Feb 2025 13:44:56 +0000 Subject: [PATCH] Evaluate DeviceScaleFactor per captured frame This is to ensure that the device_scale_factor stored per frame is the latest one according to the system settings and not an old value. Bug: chromium:383946052 Change-Id: I11e6342201678451554e6883ded48999fd996743 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/377541 Reviewed-by: Ilya Nikolaevskiy Commit-Queue: Palak Agarwal Reviewed-by: Henrik Andreassson Cr-Commit-Position: refs/heads/main@{#43924} --- .../win/dxgi_duplicator_controller.cc | 4 +- modules/desktop_capture/win/dxgi_frame.cc | 5 +-- modules/desktop_capture/win/dxgi_frame.h | 7 +--- .../win/dxgi_output_duplicator.cc | 21 ++++++---- .../win/dxgi_output_duplicator.h | 6 +-- .../win/wgc_capture_session.cc | 40 ++++++++++++------- .../desktop_capture/win/wgc_capture_session.h | 7 +--- 7 files changed, 47 insertions(+), 43 deletions(-) diff --git a/modules/desktop_capture/win/dxgi_duplicator_controller.cc b/modules/desktop_capture/win/dxgi_duplicator_controller.cc index 7b170c104b..7745f3f10d 100644 --- a/modules/desktop_capture/win/dxgi_duplicator_controller.cc +++ b/modules/desktop_capture/win/dxgi_duplicator_controller.cc @@ -189,12 +189,12 @@ DxgiDuplicatorController::Result DxgiDuplicatorController::DoDuplicate( return Result::INITIALIZATION_FAILED; } - if (!frame->Prepare(SelectedDesktopSize(monitor_id), monitor_id, - GetDeviceScaleFactor(monitor_id))) { + if (!frame->Prepare(SelectedDesktopSize(monitor_id), monitor_id)) { return Result::FRAME_PREPARE_FAILED; } frame->frame()->mutable_updated_region()->Clear(); + frame->frame()->set_device_scale_factor(GetDeviceScaleFactor(monitor_id)); if (DoDuplicateUnlocked(frame->context(), monitor_id, frame->frame())) { succeeded_duplications_++; diff --git a/modules/desktop_capture/win/dxgi_frame.cc b/modules/desktop_capture/win/dxgi_frame.cc index 1f854b50ec..55495aec26 100644 --- a/modules/desktop_capture/win/dxgi_frame.cc +++ b/modules/desktop_capture/win/dxgi_frame.cc @@ -25,9 +25,7 @@ DxgiFrame::DxgiFrame(SharedMemoryFactory* factory) : factory_(factory) {} DxgiFrame::~DxgiFrame() = default; -bool DxgiFrame::Prepare(DesktopSize size, - DesktopCapturer::SourceId source_id, - std::optional device_scale_factor) { +bool DxgiFrame::Prepare(DesktopSize size, DesktopCapturer::SourceId source_id) { if (source_id != source_id_) { // Once the source has been changed, the entire source should be copied. source_id_ = source_id; @@ -59,7 +57,6 @@ bool DxgiFrame::Prepare(DesktopSize size, } else { frame.reset(new BasicDesktopFrame(size)); } - frame->set_device_scale_factor(device_scale_factor); frame_ = SharedDesktopFrame::Wrap(std::move(frame)); } diff --git a/modules/desktop_capture/win/dxgi_frame.h b/modules/desktop_capture/win/dxgi_frame.h index 2c1c0a43ab..6a9ce868a7 100644 --- a/modules/desktop_capture/win/dxgi_frame.h +++ b/modules/desktop_capture/win/dxgi_frame.h @@ -45,11 +45,8 @@ class DxgiFrame final { // as well as Context class. friend class DxgiDuplicatorController; - // Prepares current instance with desktop size, source id and device scale - // factor. - bool Prepare(DesktopSize size, - DesktopCapturer::SourceId source_id, - std::optional device_scale_factor); + // Prepares current instance with desktop size and source id. + bool Prepare(DesktopSize size, DesktopCapturer::SourceId source_id); // Should not be called if Prepare() is not executed or returns false. Context* context(); diff --git a/modules/desktop_capture/win/dxgi_output_duplicator.cc b/modules/desktop_capture/win/dxgi_output_duplicator.cc index 7014b10396..ca224b99bb 100644 --- a/modules/desktop_capture/win/dxgi_output_duplicator.cc +++ b/modules/desktop_capture/win/dxgi_output_duplicator.cc @@ -68,18 +68,12 @@ DxgiOutputDuplicator::DxgiOutputDuplicator(const D3dDevice& device, : device_(device), output_(output), device_name_(rtc::ToUtf8(desc.DeviceName)), - desktop_rect_(RECTToDesktopRect(desc.DesktopCoordinates)) { + desktop_rect_(RECTToDesktopRect(desc.DesktopCoordinates)), + monitor_(desc.Monitor) { RTC_DCHECK(output_); RTC_DCHECK(!desktop_rect_.is_empty()); RTC_DCHECK_GT(desktop_rect_.width(), 0); RTC_DCHECK_GT(desktop_rect_.height(), 0); - DEVICE_SCALE_FACTOR device_scale_factor = DEVICE_SCALE_FACTOR_INVALID; - HRESULT hr = GetScaleFactorForMonitor(desc.Monitor, &device_scale_factor); - RTC_LOG_IF(LS_ERROR, FAILED(hr)) - << "Failed to get scale factor for monitor: " << hr; - if (device_scale_factor != DEVICE_SCALE_FACTOR_INVALID) { - device_scale_factor_ = static_cast(device_scale_factor) / 100.0f; - } } DxgiOutputDuplicator::DxgiOutputDuplicator(DxgiOutputDuplicator&& other) = @@ -425,6 +419,17 @@ int64_t DxgiOutputDuplicator::num_frames_captured() const { return num_frames_captured_; } +std::optional DxgiOutputDuplicator::device_scale_factor() const { + DEVICE_SCALE_FACTOR device_scale_factor = DEVICE_SCALE_FACTOR_INVALID; + HRESULT hr = GetScaleFactorForMonitor(monitor_, &device_scale_factor); + if (FAILED(hr)) { + RTC_LOG(LS_ERROR) << "Failed to get scale factor for monitor: " << hr; + return std::nullopt; + } + RTC_DCHECK(device_scale_factor != DEVICE_SCALE_FACTOR_INVALID); + return static_cast(device_scale_factor) / 100.0f; +} + void DxgiOutputDuplicator::TranslateRect(const DesktopVector& position) { desktop_rect_.Translate(position); RTC_DCHECK_GE(desktop_rect_.left(), 0); diff --git a/modules/desktop_capture/win/dxgi_output_duplicator.h b/modules/desktop_capture/win/dxgi_output_duplicator.h index 8bd78f787d..e2a87751d6 100644 --- a/modules/desktop_capture/win/dxgi_output_duplicator.h +++ b/modules/desktop_capture/win/dxgi_output_duplicator.h @@ -86,9 +86,7 @@ class DxgiOutputDuplicator { // Device scale factor of the monitor associated with this // DxigOutputDuplicator. - std::optional device_scale_factor() const { - return device_scale_factor_; - } + std::optional device_scale_factor() const; // Moves `desktop_rect_`. See DxgiDuplicatorController::TranslateRect(). void TranslateRect(const DesktopVector& position); @@ -134,13 +132,13 @@ class DxgiOutputDuplicator { const Microsoft::WRL::ComPtr output_; const std::string device_name_; DesktopRect desktop_rect_; + const HMONITOR monitor_; Microsoft::WRL::ComPtr duplication_; DXGI_OUTDUPL_DESC desc_; std::vector metadata_; std::unique_ptr texture_; Rotation rotation_; DesktopSize unrotated_size_; - std::optional device_scale_factor_; // After each AcquireNextFrame() function call, updated_region_(s) of all // active Context(s) need to be updated. Since they have missed the diff --git a/modules/desktop_capture/win/wgc_capture_session.cc b/modules/desktop_capture/win/wgc_capture_session.cc index 339a744de0..03e9f52a4c 100644 --- a/modules/desktop_capture/win/wgc_capture_session.cc +++ b/modules/desktop_capture/win/wgc_capture_session.cc @@ -106,21 +106,9 @@ WgcCaptureSession::WgcCaptureSession(intptr_t source_id, ABI::Windows::Graphics::SizeInt32 size) : d3d11_device_(std::move(d3d11_device)), item_(std::move(item)), - size_(size) { + size_(size), + source_id_(source_id) { RTC_CHECK(source_id); - HMONITOR monitor = 0; - if (!GetHmonitorFromDeviceIndex(source_id, &monitor)) { - monitor = MonitorFromWindow(reinterpret_cast(source_id), - /*dwFlags=*/MONITOR_DEFAULTTONEAREST); - } - DEVICE_SCALE_FACTOR device_scale_factor = DEVICE_SCALE_FACTOR_INVALID; - HRESULT hr = GetScaleFactorForMonitor(monitor, &device_scale_factor); - RTC_LOG_IF(LS_ERROR, FAILED(hr)) - << "Failed to get scale factor for monitor: " << hr; - - if (device_scale_factor != DEVICE_SCALE_FACTOR_INVALID) { - device_scale_factor_ = static_cast(device_scale_factor) / 100.0f; - } } WgcCaptureSession::~WgcCaptureSession() { @@ -473,9 +461,31 @@ HRESULT WgcCaptureSession::ProcessFrame() { } DesktopFrame* current_frame = queue_.current_frame(); - current_frame->set_device_scale_factor(device_scale_factor_); DesktopFrame* previous_frame = queue_.previous_frame(); + // If the captured window moves to another screen, the HMONITOR assosciated + // with the captured window will change. Therefore, we need to get the value + // of HMONITOR per frame. + HMONITOR monitor; + if (!GetHmonitorFromDeviceIndex(source_id_, &monitor)) { + monitor = MonitorFromWindow(reinterpret_cast(source_id_), + /*dwFlags=*/MONITOR_DEFAULTTONEAREST); + } + + // Captures the device scale factor of the monitor where the frame is captured + // from. This value is the same as the scale from windows settings. Valid + // values are some distinct numbers in the range of [1,5], for example, + // 1, 1.5, 2.5, etc. + DEVICE_SCALE_FACTOR device_scale_factor = DEVICE_SCALE_FACTOR_INVALID; + HRESULT scale_factor_hr = + GetScaleFactorForMonitor(monitor, &device_scale_factor); + RTC_LOG_IF(LS_ERROR, FAILED(scale_factor_hr)) + << "Failed to get scale factor for monitor: " << scale_factor_hr; + if (device_scale_factor != DEVICE_SCALE_FACTOR_INVALID) { + current_frame->set_device_scale_factor( + static_cast(device_scale_factor) / 100.0f); + } + // Will be set to true while copying the frame data to the `current_frame` if // we can already determine that the content of the new frame differs from the // previous. The idea is to get a low-complexity indication of if the content diff --git a/modules/desktop_capture/win/wgc_capture_session.h b/modules/desktop_capture/win/wgc_capture_session.h index a12fc0795d..f6c42673ed 100644 --- a/modules/desktop_capture/win/wgc_capture_session.h +++ b/modules/desktop_capture/win/wgc_capture_session.h @@ -149,11 +149,8 @@ class WgcCaptureSession final { // false. DesktopRegion damage_region_; - // Captures the device scale factor of the monitor where the frame is captured - // from. This value is the same as the scale from windows settings. Valid - // values are some distinct numbers in the range of [1,5], for example, - // 1, 1.5, 2.5, etc. - std::optional device_scale_factor_; + // The unique id to represent a Source of current DesktopCapturer. + intptr_t source_id_; SequenceChecker sequence_checker_; };