Skip to content

capture(wayland): fix black screen and pts timing on gst-launch#9

Merged
omarroth merged 1 commit into
omarroth:mainfrom
domenkozar:go-gst-capture
Jul 2, 2026
Merged

capture(wayland): fix black screen and pts timing on gst-launch#9
omarroth merged 1 commit into
omarroth:mainfrom
domenkozar:go-gst-capture

Conversation

@domenkozar

@domenkozar domenkozar commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

Keep the gst-launch CLI for the Wayland portal path, but fold in two fixes found while prototyping a go-gst version:

  • vapostproc ! video/x-raw,format=I420 imports the portal's DMA-BUF via VA-API (plain videoconvert fails to negotiate DMA-BUF on many drivers) and forces 4:2:0. RGB screens otherwise make x264enc emit "High 4:4:4 Predictive", which most receiver decoders reject (black screen).
  • videorate drop-only=true skip-to-first=true ! framerate caps re-stamps buffers onto a regular fps timeline; the portal can deliver pts=0, which confuses encoder/muxer timing.

No new dependencies — the build stays pure Go (no CGO); GStreamer is still only invoked as the gst-launch-1.0 external binary.

Verified end-to-end: mirrors a Wayland desktop to a non-Apple AirPlay 2 receiver (Hisense), yuv420p, no crash.

@domenkozar domenkozar marked this pull request as draft June 24, 2026 15:29
@domenkozar domenkozar marked this pull request as ready for review June 24, 2026 16:28
@domenkozar

Copy link
Copy Markdown
Contributor Author

@omarroth this is ready for review when you have a moment.

It swaps the gst-launch subprocess for the go-gst library and fixes the black-screen issues on modern Wayland/Mesa (DMA-BUF import via vapostproc, 4:2:0 I420, PTS re-stamp). It also fixes two in-process cgo crashes that the CLI path never hit: a missing gst.Init() (segfault in gst_parse_launch) and an appsink SetCallbacks use-after-free (now a blocking PullSample loop).

Verified end-to-end mirroring a niri desktop to a non-Apple AirPlay 2 receiver (Hisense), yuv420p, no crash. Happy to adjust anything.

@domenkozar domenkozar changed the title capture(wayland): use the go-gst library instead of gst-launch capture(wayland): fix black screen and pts timing on gst-launch Jun 25, 2026
Keep the gst-launch CLI for the Wayland portal path, but fold in two fixes:

  - vapostproc ! video/x-raw,format=I420 imports the portal's DMA-BUF via
    VA-API (plain videoconvert fails to negotiate DMA-BUF on many drivers)
    and forces 4:2:0 — RGB screens otherwise make x264enc emit "High 4:4:4
    Predictive", which most receiver decoders reject (black screen).

  - videorate drop-only=true skip-to-first=true ! framerate caps re-stamps
    buffers onto a regular fps timeline; the portal can deliver pts=0, which
    confuses encoder/muxer timing.

Verified end-to-end: mirrors a Wayland desktop to a non-Apple AirPlay 2
receiver (Hisense), yuv420p, no crash.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@domenkozar

Copy link
Copy Markdown
Contributor Author

@omarroth ready for review

@omarroth

omarroth commented Jul 2, 2026

Copy link
Copy Markdown
Owner

Works for me 👍. Could you also provide the player (device and wayland environment) and model of HiSense device you're attempting to stream to? If possible I'd like to start building a compatibility matrix for preventing breakage as things get moved around.

Also I expect you're aware from #8, but please make sure you're comfortable providing this code under the terms of the LGPL or later since the license has changed.

Otherwise good to merge.

@domenkozar

Copy link
Copy Markdown
Contributor Author

Sure! Sender setup for the compatibility matrix:

  • Device: laptop with AMD Ryzen 7 7840S (Radeon 780M iGPU, amdgpu kernel driver, Mesa VA-API)
  • OS: NixOS 26.05, kernel 7.0.10
  • Compositor: niri 26.04 (Wayland)
  • Screen capture: xdg-desktop-portal 1.20.4 with the xdg-desktop-portal-gnome backend, PipeWire 1.6.5
  • GStreamer: 1.26.11 (the gst-launch-1.0 binary the pipeline shells out to)

Receiver: Hisense 55A6QU. From its AirPlay advertisement: features=0x38bcf46007f8ad0, no FairPlay SAP (FPSAP bit not advertised), so the session falls back to pair-verify DataStream setup.

On the license: yes, I'm comfortable contributing this under LGPL-3.0-or-later.

@omarroth omarroth merged commit a65f5ab into omarroth:main Jul 2, 2026
3 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