wayland: Support dynamic resolution changes of pw stream

This change adds support for dynamic resolution adjustment
of pipewire stream.

Bug: chromium:1291247
Change-Id: I87e02484920f795a053a814eb872834ab22c1bd3
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/263680
Commit-Queue: Salman Malik <salmanmalik@google.com>
Reviewed-by: Alexander Cooper <alcooper@chromium.org>
Cr-Commit-Position: refs/heads/main@{#37010}
This commit is contained in:
Salman Malik
2022-05-26 17:50:15 +00:00
committed by WebRTC LUCI CQ
parent 2d4207e85a
commit 45a22ffbb7
5 changed files with 65 additions and 4 deletions

View File

@ -144,6 +144,8 @@ class RTC_EXPORT DesktopCapturer {
#if defined(WEBRTC_USE_PIPEWIRE) || defined(WEBRTC_USE_X11)
static bool IsRunningUnderWayland();
virtual void UpdateResolution(uint32_t width, uint32_t height){};
#endif // defined(WEBRTC_USE_PIPEWIRE) || defined(WEBRTC_USE_X11)
#if defined(WEBRTC_USE_GIO)

View File

@ -58,6 +58,13 @@ void BaseCapturerPipeWire::OnScreenCastSessionClosed() {
}
}
void BaseCapturerPipeWire::UpdateResolution(uint32_t width, uint32_t height) {
if (!capturer_failed_) {
options_.screencast_stream()->UpdateScreenCastStreamResolution(width,
height);
}
}
void BaseCapturerPipeWire::Start(Callback* callback) {
RTC_DCHECK(!callback_);
RTC_DCHECK(callback);

View File

@ -45,6 +45,7 @@ class BaseCapturerPipeWire : public DesktopCapturer,
uint32_t stream_node_id,
int fd) override;
void OnScreenCastSessionClosed() override;
void UpdateResolution(uint32_t width, uint32_t height) override;
xdg_portal::SessionDetails GetSessionDetails();

View File

@ -89,6 +89,7 @@ class SharedScreenCastStreamPrivate {
int fd,
uint32_t width = 0,
uint32_t height = 0);
void UpdateScreenCastStreamResolution(uint32_t width, uint32_t height);
void StopScreenCastStream();
std::unique_ptr<DesktopFrame> CaptureFrame();
std::unique_ptr<MouseCursor> CaptureCursor();
@ -130,6 +131,13 @@ class SharedScreenCastStreamPrivate {
// Version of the library used to run our code
PipeWireVersion pw_client_version_;
// Resolution parameters.
uint32_t width_ = 0;
uint32_t height_ = 0;
webrtc::Mutex resolution_lock_;
// Resolution changes are processed during buffer processing.
bool pending_resolution_change_ RTC_GUARDED_BY(&resolution_lock_) = false;
// event handlers
pw_core_events pw_core_events_ = {};
pw_stream_events pw_stream_events_ = {};
@ -329,18 +337,24 @@ void SharedScreenCastStreamPrivate::OnRenegotiateFormat(void* data, uint64_t) {
spa_pod_builder builder = spa_pod_builder{buffer, sizeof(buffer)};
std::vector<const spa_pod*> params;
struct spa_rectangle resolution =
SPA_RECTANGLE(that->width_, that->height_);
webrtc::MutexLock lock(&that->resolution_lock_);
for (uint32_t format : {SPA_VIDEO_FORMAT_BGRA, SPA_VIDEO_FORMAT_RGBA,
SPA_VIDEO_FORMAT_BGRx, SPA_VIDEO_FORMAT_RGBx}) {
if (!that->modifiers_.empty()) {
params.push_back(BuildFormat(&builder, format, that->modifiers_,
/*resolution=*/nullptr));
params.push_back(BuildFormat(
&builder, format, that->modifiers_,
that->pending_resolution_change_ ? &resolution : nullptr));
}
params.push_back(BuildFormat(&builder, format, /*modifiers=*/{},
/*resolution=*/nullptr));
params.push_back(BuildFormat(
&builder, format, /*modifiers=*/{},
that->pending_resolution_change_ ? &resolution : nullptr));
}
pw_stream_update_params(that->pw_stream_, params.data(), params.size());
that->pending_resolution_change_ = false;
}
}
@ -374,6 +388,8 @@ bool SharedScreenCastStreamPrivate::StartScreenCastStream(
int fd,
uint32_t width,
uint32_t height) {
width_ = width;
height_ = height;
#if defined(WEBRTC_DLOPEN_PIPEWIRE)
StubPathMap paths;
@ -502,6 +518,35 @@ bool SharedScreenCastStreamPrivate::StartScreenCastStream(
return true;
}
RTC_NO_SANITIZE("cfi-icall")
void SharedScreenCastStreamPrivate::UpdateScreenCastStreamResolution(
uint32_t width,
uint32_t height) {
if (!width || !height) {
RTC_LOG(LS_WARNING) << "Bad resolution specified: " << width << "x"
<< height;
return;
}
if (!pw_main_loop_) {
RTC_LOG(LS_WARNING) << "No main pipewire loop, ignoring resolution change";
return;
}
if (!renegotiate_) {
RTC_LOG(LS_WARNING) << "Can not renegotiate stream params, ignoring "
<< "resolution change";
return;
}
if (width_ != width || height_ != height) {
width_ = width;
height_ = height;
{
webrtc::MutexLock lock(&resolution_lock_);
pending_resolution_change_ = true;
}
pw_loop_signal_event(pw_thread_loop_get_loop(pw_main_loop_), renegotiate_);
}
}
void SharedScreenCastStreamPrivate::StopScreenCastStream() {
if (pw_stream_) {
pw_stream_disconnect(pw_stream_);
@ -751,6 +796,11 @@ bool SharedScreenCastStream::StartScreenCastStream(uint32_t stream_node_id,
return private_->StartScreenCastStream(stream_node_id, fd, width, height);
}
void SharedScreenCastStream::UpdateScreenCastStreamResolution(uint32_t width,
uint32_t height) {
private_->UpdateScreenCastStreamResolution(width, height);
}
void SharedScreenCastStream::StopScreenCastStream() {
private_->StopScreenCastStream();
}

View File

@ -34,6 +34,7 @@ class RTC_EXPORT SharedScreenCastStream
int fd,
uint32_t width = 0,
uint32_t height = 0);
void UpdateScreenCastStreamResolution(uint32_t width, uint32_t height);
void StopScreenCastStream();
// Below functions return the most recent information we get from a