Skip to content

fix(capture): map the DMA-BUF frames niri actually sends - #26

Merged
panxuc merged 5 commits into
panxuc:masterfrom
Aibeto:fix/pipewire-dmabuf-frames
Oct 15, 2026
Merged

panxuc merged 5 commits into
panxuc:masterfrom
Aibeto:fix/pipewire-dmabuf-frames

Conversation

@Aibeto

@Aibeto Aibeto commented Oct 13, 2026

Copy link
Copy Markdown
Contributor

uur run reported "No Wayland frames arrived within 120 seconds" on a session where the portal handshake succeeded. The session log showed the stream never leaving negotiation:

portal session ready (video node 73)
stream state: connecting
stream state: paused
stream state: error - no more input formats
stream state: unconnected

Three separate defects in uur-pw-capture:

  1. The format filter omitted modifier. niri marks that property MANDATORY (SPA flags 0x18), and SPA filtering fails unless both sides carry a mandatory property -- which surfaces as "no more input formats". The filter now advertises LINEAR, the layout the frame protocol already assumes.

  2. on_process only handled data != NULL and SPA_DATA_MemFd. niri delivers SPA_DATA_DmaBuf planes, which carry an fd and no pointer, so every frame was dropped in silence. Since the session negotiates LINEAR, that fd is directly mappable without GBM/EGL; the helper now mmaps it. A non-linear modifier is refused instead of publishing garbage.

  3. DMA-BUF producers leave chunk->size and maxsize at 1. Both the mapping length and the row count were derived from those, so the mmap covered one byte and rows came out zero -- publishing an all-black frame. Both now use the negotiated stride and height.

Verified on niri 26.04 with Wine 11.19: the stream reaches streaming, ~60 fps (1195 frames in 20 s), and the published frame decodes to the real desktop rather than black.

@Aibeto

Aibeto commented Oct 13, 2026

Copy link
Copy Markdown
Contributor Author

need review again
remind in #28

Aibeto and others added 2 commits October 15, 2026 14:47
`uur run` reported "No Wayland frames arrived within 120 seconds" on a
session where the portal handshake succeeded. The session log showed the
stream never leaving negotiation:

    portal session ready (video node 73)
    stream state: connecting
    stream state: paused
    stream state: error - no more input formats
    stream state: unconnected

Three separate defects in `uur-pw-capture`:

1. The format filter omitted `modifier`. niri marks that property
   MANDATORY (SPA flags 0x18), and SPA filtering fails unless both sides
   carry a mandatory property -- which surfaces as "no more input
   formats". The filter now advertises LINEAR, the layout the frame
   protocol already assumes.

2. `on_process` only handled `data != NULL` and `SPA_DATA_MemFd`. niri
   delivers SPA_DATA_DmaBuf planes, which carry an fd and no pointer, so
   every frame was dropped in silence. Since the session negotiates
   LINEAR, that fd is directly mappable without GBM/EGL; the helper now
   mmaps it. A non-linear modifier is refused instead of publishing
   garbage.

3. DMA-BUF producers leave `chunk->size` and `maxsize` at 1. Both the
   mapping length and the row count were derived from those, so the mmap
   covered one byte and `rows` came out zero -- publishing an all-black
   frame. Both now use the negotiated stride and height.

Verified on niri 26.04 with Wine 11.19: the stream reaches `streaming`,
~60 fps (1195 frames in 20 s), and the published frame decodes to the
real desktop rather than black.
Use immutable transport files across geometry changes and remap Wine readers safely. Bound stream recovery and preserve portal stop-sharing intent. Refs panxuc#29.
@panxuc
panxuc force-pushed the fix/pipewire-dmabuf-frames branch from 39d4411 to c48cd00 Compare October 15, 2026 06:48
Subscribe before starting on the portal-owned D-Bus connection and accept the real Session.Closed dictionary body. Correlate Mutter's close-before-MonitorsChanged ordering without restarting an explicit Stop Sharing session.

Verified in a private GNOME 51.1 namespace with real GBM DMA-BUF, 100/125 percent scaling, portrait and landscape, and native Stop Sharing. Existing 48 tests and strict clippy pass. Real Wine GDI reader captured 120 final-run frames across four layout changes with no hook fallbacks. No test scripts added.
@panxuc
panxuc merged commit a5e2aa4 into panxuc:master Oct 15, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants