-
Notifications
You must be signed in to change notification settings - Fork 108
Expose desktop capturer #725
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
Exports VideoFrameBuffer::Scale for every buffer by extending the livekit::*Buffer types.
Implements screen sharing by exposing libwebrtc's DesktopCapturer. A few platform specific notes: - macos: * It is using screen capture kit and the system picker by default. If the system picker is disabled then get_sources returns an empty list when trying to capture a display. The display native id needs to be acquired using different means from the client. - linux: * With pipewire the only way to select window or display is via the system picker.
#[cfg(target_os = "linux")] | ||
{ | ||
/* This is needed for getting the system picker for screen sharing. */ | ||
use glib::MainLoop; | ||
let main_loop = MainLoop::new(None, false); | ||
let _handle = std::thread::spawn(move || { | ||
main_loop.run(); | ||
}); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the need for this GLib event loop? With the GStreamer Rust bindings for example, GStreamer events are usually handled by a GLib event loop, but GStreamer has an API to register an event callback that the library calls internally, which can be used from Rust to send events to a Rust thread or async stream over a channel. This way the Rust program calling the library doesn't need to setup its own GLib event loop. Here's an example: https://codeberg.org/Be.ing/dance-video-recorder/src/commit/4aab73f5514ff08000ef330f221dc6035831a4ee/src/camera_monitor.rs#L22
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks I didn't know about this. I will update the example to do it this way.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure if such an approach is feasible without a clearer idea of what the need for the GLib event loop is.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the example I linked above, the GStreamer bindings are creating a futures_channel::mpsc under the hood to create an ergonomic Rust stream API: https://gitlab.freedesktop.org/gstreamer/gstreamer-rs/-/blob/c533fe960af057c55916ba3fb48c42837da98565/gstreamer/src/bus.rs#L345
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the need for the GLib event loop is
The event loop is needed for opening the system ui picker. It is related to the xdg_portal setup. Maybe there is something here. I need to have a better look.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, so libwebrtc invokes GDBus under the hood. That's inconvenient for usage from Rust, but okay. At least this requirement should be documented for Livekit.
It would be nice to use zbus/ashpd instead, but at a quick glance that would require somewhat extensive changes to libwebrtc's C++ code to call into Rust (via cxx) instead of GDBus. If you're up for doing that, that'd be great, but no pressing need for it. I might give that a try eventually.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be nice if Livekit handled starting the GLib main loop so users of the library wouldn't have to, but that wouldn't be good for applications that are already using GLib for something such as the GStreamer or GTK Rust bindings. So, best to leave it to the user of the library with documentation.
#[cfg(target_os = "linux")] | ||
{ | ||
options.set_pipewire_capturer(true); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What happens if this is false? I presume libwebrtc tries to capture via X11? If so, this should check at runtime whether it's being run under X11 or Wayland rather than assuming target_os = "linux"
means Wayland.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep the proper way would be to check on runtime and not enable it (I have no idea if pipewire works with X11). I didn't do it here because it would have taken more time to set up the X11 dependencies and my vm. I will try to test on X11 during the week.
I will give this a closer look and testing this week. Big thanks for adding a new example program! |
EDIT: Nevermind, I checked out the wrong branch.
|
How do I build the example? I don't see any documentation how this build system works and libwebrtc-sys's build.rs is quite complicated.
|
That build_linux.sh script fails. I'm puzzled what it's doing. It seems to be downloading a bunch of stuff including a Debian image or something?? And building Abseil... does libwebrtc depend on Abseil? Then it fails to find a header from glibc.
|
I think I need to rebase #648 to get this to build... this build system needs some work. |
After 3 days of yak shaving, I got libwebrtc to build locally with #730. I had to make a few changes to this branch to get it to build, so I made a PR for your fork: gethopp#2. Now I am wondering what LIVEKIT_URL to use for development. Is there a test server I can use? Or a tool for running a test server locally? |
Implements screen sharing by exposing libwebrtc's
DesktopCapturer
.A few notes:
GetSourceList
to actually get the available displays without the system picker. I could port my patch to your libwebrtc fork if you want. For selecting windowsGetSourceList
seems to work.Tested on:
This is related to #92 and zed-industries/zed#28754.