mirror of
https://github.com/rustdesk/rustdesk.git
synced 2026-05-18 12:04:48 +03:00
On Wayland compositors whose xdg-desktop-portal backend exposes screencast frames as DMA-BUF buffers — notably xdg-desktop-portal-cosmic 0.1.0 on Pop!_OS 24.04 / COSMIC — inbound screen capture fails. PipeWireRecorder links pipewiresrc directly to an appsink whose caps only accept video/x-raw BGRx/RGBx in system memory. That format set is too narrow for the portal's buffer-type / modifier negotiation, which collapses with: pw.link: negotiating -> error no more output formats (-22) gstpipewiresrc: stream error: no more output formats gstbasesrc: streaming stopped, reason not-negotiated (-4) ERROR src/server/wayland.rs: Failed scrap Element failed to change its state Inserting a videoconvert element between pipewiresrc and appsink widens the negotiable format set to any system-memory video/x-raw format, giving the portal room to settle on a format it can deliver via its SHM path. videoconvert then converts to the BGRx/RGBx the appsink expects. Verified on Pop!_OS 24.04 / COSMIC with gst-launch, before and after: # fails (current behaviour): gst-launch-1.0 pipewiresrc path=N ! video/x-raw,format=BGRx ! fakesink # works (with this change): gst-launch-1.0 pipewiresrc path=N ! videoconvert ! video/x-raw,format=BGRx ! fakesink After the change, inbound connections capture and stream the desktop normally and the "Failed scrap" error no longer occurs. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Derived from https://github.com/quadrupleslap/scrap
scrap
Scrap records your screen! At least it does if you're on Windows, macOS, or Linux.
Usage
[dependencies]
scrap = "0.5"
Its API is as simple as it gets!
struct Display; /// A screen.
struct Frame; /// An array of the pixels that were on-screen.
struct Capturer; /// A recording instance.
impl Capturer {
/// Begin recording.
pub fn new(display: Display) -> io::Result<Capturer>;
/// Try to get a frame.
/// Returns WouldBlock if it's not ready yet.
pub fn frame<'a>(&'a mut self) -> io::Result<Frame<'a>>;
pub fn width(&self) -> usize;
pub fn height(&self) -> usize;
}
impl Display {
/// The primary screen.
pub fn primary() -> io::Result<Display>;
/// All the screens.
pub fn all() -> io::Result<Vec<Display>>;
pub fn width(&self) -> usize;
pub fn height(&self) -> usize;
}
impl<'a> ops::Deref for Frame<'a> {
/// A frame is just an array of bytes.
type Target = [u8];
}
The Frame Format
- The frame format is guaranteed to be packed BGRA.
- The width and height are guaranteed to remain constant.
- The stride might be greater than the width, and it may also vary between frames.
System Requirements
| OS | Minimum Requirements |
|---|---|
| macOS | macOS 10.8 |
| Linux | XCB + SHM + RandR |
| Windows | DirectX 11.1 |