Avoids spamming WebRTC.DesktopCapture.Win.WgcCaptureSessionGetFrameResult with FrameDropped
Without this change a FrameDropped sample will be added to
WebRTC.DesktopCapture.Win.WgcCaptureSessionGetFrameResult at the
current capture rate as long as a captured window is minimized.
Bug: webrtc:1314868
Change-Id: I9b68675486642e7ca25674df689c207ac94a206e
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/323882
Commit-Queue: Alexander Cooper <alcooper@chromium.org>
Reviewed-by: Alexander Cooper <alcooper@chromium.org>
Cr-Commit-Position: refs/heads/main@{#40969}
diff --git a/modules/desktop_capture/win/wgc_capture_session.cc b/modules/desktop_capture/win/wgc_capture_session.cc
index 827f257..2f7fac9 100644
--- a/modules/desktop_capture/win/wgc_capture_session.cc
+++ b/modules/desktop_capture/win/wgc_capture_session.cc
@@ -256,10 +256,16 @@
<< "Unable to process a valid frame even after trying 10 times.";
}
-bool WgcCaptureSession::GetFrame(std::unique_ptr<DesktopFrame>* output_frame) {
+bool WgcCaptureSession::GetFrame(std::unique_ptr<DesktopFrame>* output_frame,
+ bool source_should_be_capturable) {
RTC_DCHECK_RUN_ON(&sequence_checker_);
- EnsureFrame();
+ // Try to process the captured frame and wait some if needed. Avoid trying
+ // if we know that the source will not be capturable. This can happen e.g.
+ // when captured window is minimized and if EnsureFrame() was called in this
+ // state a large amount of kFrameDropped errors would be logged.
+ if (source_should_be_capturable)
+ EnsureFrame();
// Return a NULL frame and false as `result` if we still don't have a valid
// frame. This will lead to a DesktopCapturer::Result::ERROR_PERMANENT being
diff --git a/modules/desktop_capture/win/wgc_capture_session.h b/modules/desktop_capture/win/wgc_capture_session.h
index 499c75e..8084bf1 100644
--- a/modules/desktop_capture/win/wgc_capture_session.h
+++ b/modules/desktop_capture/win/wgc_capture_session.h
@@ -44,7 +44,8 @@
HRESULT StartCapture(const DesktopCaptureOptions& options);
// Returns a frame from the local frame queue, if any are present.
- bool GetFrame(std::unique_ptr<DesktopFrame>* output_frame);
+ bool GetFrame(std::unique_ptr<DesktopFrame>* output_frame,
+ bool source_should_be_capturable);
bool IsCaptureStarted() const {
RTC_DCHECK_RUN_ON(&sequence_checker_);
diff --git a/modules/desktop_capture/win/wgc_capture_source.cc b/modules/desktop_capture/win/wgc_capture_source.cc
index 24e6129..9eab3db 100644
--- a/modules/desktop_capture/win/wgc_capture_source.cc
+++ b/modules/desktop_capture/win/wgc_capture_source.cc
@@ -29,6 +29,10 @@
: source_id_(source_id) {}
WgcCaptureSource::~WgcCaptureSource() = default;
+bool WgcCaptureSource::ShouldBeCapturable() {
+ return true;
+}
+
bool WgcCaptureSource::IsCapturable() {
// If we can create a capture item, then we can capture it. Unfortunately,
// we can't cache this item because it may be created in a different COM
@@ -105,9 +109,17 @@
window_rect.bottom - window_rect.top};
}
+// Light-weight version of IsCapturable(). Avoids calling
+// WgcCaptureSource::IsCapturable() which allocates/deallocates a new COM object
+// for each call. Will return false when a window has been minimized.
+bool WgcWindowSource::ShouldBeCapturable() {
+ return IsWindowValidAndVisible(reinterpret_cast<HWND>(GetSourceId()));
+}
+
bool WgcWindowSource::IsCapturable() {
- if (!IsWindowValidAndVisible(reinterpret_cast<HWND>(GetSourceId())))
+ if (!ShouldBeCapturable()) {
return false;
+ }
return WgcCaptureSource::IsCapturable();
}
diff --git a/modules/desktop_capture/win/wgc_capture_source.h b/modules/desktop_capture/win/wgc_capture_source.h
index d1275b6..87227fc 100644
--- a/modules/desktop_capture/win/wgc_capture_source.h
+++ b/modules/desktop_capture/win/wgc_capture_source.h
@@ -33,6 +33,7 @@
virtual ~WgcCaptureSource();
virtual DesktopVector GetTopLeft() = 0;
+ virtual bool ShouldBeCapturable();
virtual bool IsCapturable();
virtual bool FocusOnSource();
virtual ABI::Windows::Graphics::SizeInt32 GetSize();
@@ -99,6 +100,7 @@
DesktopVector GetTopLeft() override;
ABI::Windows::Graphics::SizeInt32 GetSize() override;
+ bool ShouldBeCapturable() override;
bool IsCapturable() override;
bool FocusOnSource() override;
diff --git a/modules/desktop_capture/win/wgc_capturer_win.cc b/modules/desktop_capture/win/wgc_capturer_win.cc
index 20d4eb9..9c54559 100644
--- a/modules/desktop_capture/win/wgc_capturer_win.cc
+++ b/modules/desktop_capture/win/wgc_capturer_win.cc
@@ -323,7 +323,8 @@
}
std::unique_ptr<DesktopFrame> frame;
- if (!capture_session->GetFrame(&frame)) {
+ if (!capture_session->GetFrame(&frame,
+ capture_source_->ShouldBeCapturable())) {
RTC_LOG(LS_ERROR) << "GetFrame failed.";
ongoing_captures_.erase(capture_source_->GetSourceId());
callback_->OnCaptureResult(DesktopCapturer::Result::ERROR_PERMANENT,