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) #if defined(WEBRTC_USE_PIPEWIRE) || defined(WEBRTC_USE_X11)
static bool IsRunningUnderWayland(); static bool IsRunningUnderWayland();
virtual void UpdateResolution(uint32_t width, uint32_t height){};
#endif // defined(WEBRTC_USE_PIPEWIRE) || defined(WEBRTC_USE_X11) #endif // defined(WEBRTC_USE_PIPEWIRE) || defined(WEBRTC_USE_X11)
#if defined(WEBRTC_USE_GIO) #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) { void BaseCapturerPipeWire::Start(Callback* callback) {
RTC_DCHECK(!callback_); RTC_DCHECK(!callback_);
RTC_DCHECK(callback); RTC_DCHECK(callback);

View File

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

View File

@ -89,6 +89,7 @@ class SharedScreenCastStreamPrivate {
int fd, int fd,
uint32_t width = 0, uint32_t width = 0,
uint32_t height = 0); uint32_t height = 0);
void UpdateScreenCastStreamResolution(uint32_t width, uint32_t height);
void StopScreenCastStream(); void StopScreenCastStream();
std::unique_ptr<DesktopFrame> CaptureFrame(); std::unique_ptr<DesktopFrame> CaptureFrame();
std::unique_ptr<MouseCursor> CaptureCursor(); std::unique_ptr<MouseCursor> CaptureCursor();
@ -130,6 +131,13 @@ class SharedScreenCastStreamPrivate {
// Version of the library used to run our code // Version of the library used to run our code
PipeWireVersion pw_client_version_; 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 // event handlers
pw_core_events pw_core_events_ = {}; pw_core_events pw_core_events_ = {};
pw_stream_events pw_stream_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)}; spa_pod_builder builder = spa_pod_builder{buffer, sizeof(buffer)};
std::vector<const spa_pod*> params; 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, for (uint32_t format : {SPA_VIDEO_FORMAT_BGRA, SPA_VIDEO_FORMAT_RGBA,
SPA_VIDEO_FORMAT_BGRx, SPA_VIDEO_FORMAT_RGBx}) { SPA_VIDEO_FORMAT_BGRx, SPA_VIDEO_FORMAT_RGBx}) {
if (!that->modifiers_.empty()) { if (!that->modifiers_.empty()) {
params.push_back(BuildFormat(&builder, format, that->modifiers_, params.push_back(BuildFormat(
/*resolution=*/nullptr)); &builder, format, that->modifiers_,
that->pending_resolution_change_ ? &resolution : nullptr));
} }
params.push_back(BuildFormat(&builder, format, /*modifiers=*/{}, params.push_back(BuildFormat(
/*resolution=*/nullptr)); &builder, format, /*modifiers=*/{},
that->pending_resolution_change_ ? &resolution : nullptr));
} }
pw_stream_update_params(that->pw_stream_, params.data(), params.size()); 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, int fd,
uint32_t width, uint32_t width,
uint32_t height) { uint32_t height) {
width_ = width;
height_ = height;
#if defined(WEBRTC_DLOPEN_PIPEWIRE) #if defined(WEBRTC_DLOPEN_PIPEWIRE)
StubPathMap paths; StubPathMap paths;
@ -502,6 +518,35 @@ bool SharedScreenCastStreamPrivate::StartScreenCastStream(
return true; 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() { void SharedScreenCastStreamPrivate::StopScreenCastStream() {
if (pw_stream_) { if (pw_stream_) {
pw_stream_disconnect(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); 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() { void SharedScreenCastStream::StopScreenCastStream() {
private_->StopScreenCastStream(); private_->StopScreenCastStream();
} }

View File

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