blob: f4993575ad7f248712ec8a79143e67e8a5c374a3 [file]
// Copyright 2026 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "remoting/protocol/desktop_capturer_wrapper.h"
#include <cstdint>
#include <memory>
#include <utility>
#include "base/check.h"
#include "base/functional/bind.h"
#include "base/functional/callback.h"
#include "base/logging.h"
#include "base/notimplemented.h"
#include "base/threading/thread_checker.h"
#include "build/build_config.h"
#include "remoting/protocol/webrtc_frame_scheduler_constant_rate.h"
#include "third_party/webrtc/modules/desktop_capture/desktop_capturer.h"
#include "third_party/webrtc/modules/desktop_capture/desktop_frame.h"
#include "third_party/webrtc/modules/desktop_capture/shared_memory.h"
#if defined(WEBRTC_USE_GIO)
#include "base/notreached.h"
#include "third_party/webrtc/modules/desktop_capture/desktop_capture_metadata.h"
#endif
namespace remoting {
DesktopCapturerWrapper::DesktopCapturerWrapper(
std::unique_ptr<webrtc::DesktopCapturer> capturer)
: capturer_(std::move(capturer)),
scheduler_(
std::make_unique<protocol::WebrtcFrameSchedulerConstantRate>()) {
DETACH_FROM_THREAD(thread_checker_);
DCHECK(capturer_);
}
DesktopCapturerWrapper::~DesktopCapturerWrapper() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
}
void DesktopCapturerWrapper::Start(Callback* callback) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
DCHECK(!callback_);
callback_ = callback;
if (capturer_) {
capturer_->Start(this);
}
scheduler_->Start(base::BindRepeating(
&DesktopCapturerWrapper::CaptureFrameInternal, base::Unretained(this)));
}
void DesktopCapturerWrapper::SetSharedMemoryFactory(
std::unique_ptr<webrtc::SharedMemoryFactory> shared_memory_factory) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
if (capturer_) {
capturer_->SetSharedMemoryFactory(std::move(shared_memory_factory));
}
}
void DesktopCapturerWrapper::CaptureFrame() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
// This method should not be called directly, the scheduler will call
// CaptureFrameInternal().
// TODO: crbug.com/375470501 - Either add NOTREACHED() or just delete this
// method once chromotocol is removed.
}
void DesktopCapturerWrapper::CaptureFrameInternal() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
// WebrtcVideoStream expects OnFrameCaptureStart() to be called to create the
// frame stats. However, currently only the Wayland SharedScreencastStream
// calls OnFrameCaptureStart(). So we explicitly call it here. If the
// underlying capturer calls OnFrameCaptureStart(), WebrtcVideoStream will
// just override its stats, which is harmless.
callback_->OnFrameCaptureStart();
if (capturer_) {
capturer_->CaptureFrame();
} else {
OnCaptureResult(webrtc::DesktopCapturer::Result::ERROR_PERMANENT, nullptr);
}
}
bool DesktopCapturerWrapper::GetSourceList(SourceList* sources) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
NOTIMPLEMENTED();
return false;
}
bool DesktopCapturerWrapper::SelectSource(SourceId id) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
if (capturer_) {
return capturer_->SelectSource(id);
}
return false;
}
void DesktopCapturerWrapper::SetMaxFrameRate(std::uint32_t max_frame_rate) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
scheduler_->SetMaxFramerateFps(max_frame_rate);
if (capturer_) {
capturer_->SetMaxFrameRate(max_frame_rate);
}
}
void DesktopCapturerWrapper::Pause(bool pause) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
scheduler_->Pause(pause);
}
void DesktopCapturerWrapper::BoostCaptureRate(base::TimeDelta capture_interval,
base::TimeDelta duration) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
scheduler_->BoostCaptureRate(capture_interval, duration);
}
void DesktopCapturerWrapper::OnFrameCaptureStart() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
callback_->OnFrameCaptureStart();
}
void DesktopCapturerWrapper::OnCaptureResult(
webrtc::DesktopCapturer::Result result,
std::unique_ptr<webrtc::DesktopFrame> frame) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
scheduler_->OnFrameCaptured(frame.get());
callback_->OnCaptureResult(result, std::move(frame));
}
#if defined(WEBRTC_USE_GIO)
void DesktopCapturerWrapper::GetMetadataAsync(
base::OnceCallback<void(webrtc::DesktopCaptureMetadata)> callback) {
NOTREACHED() << "Use DesktopCapturerProxy instead!";
}
#endif
} // namespace remoting