[PR #45] [MERGED] fix(vulkan): clear PTS on recycled encode-src ring buffers so do_timestamp restamps #48

Closed
opened 2026-10-15 12:47:54 +00:00 by bsakaguchi · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/games-on-whales/gst-wayland-display/pull/45
Author: @salty2011
Created: 7/26/2026
Status: ✅ Merged
Merged: 8/16/2026
Merged by: @JBailes

Base: feat/vulkan-encode ← Head: fix/vulkan-encode-src-pts


📝 Commits (2)

  • 35da978 fix(vulkan): clear PTS on recycled encode-src ring buffers so do_timestamp restamps
  • 7853a24 review: move PTS reset into convert_inner after the reuse gate

📊 Changes

1 file changed (+27 additions, -0 deletions)

View changed files

📝 wayland-display-core/src/utils/vulkan_nv12.rs (+27 -0)

📄 Description

VulkanNv12::to_gst_buffer() returns a bare clone of the current ring slot's persistent GstBuffer. waylanddisplaysrc runs with set_do_timestamp(true), which only stamps a buffer whose PTS is GST_CLOCK_TIME_NONE — and a recycled slot buffer still carries the PTS from its previous use, so do_timestamp skips it.

With the default ring depth of 4, the exported PTS therefore degenerate to four recurring values, non-monotonic and duplicated across frames. Live trace on my host: 99.9% of frames shared a timestamp with another frame, 25% were non-monotonic, and exactly four distinct RTP timestamps cycled forever.

Downstream that is fatal for WebRTC: rtph264pay derives RTP timestamps from those PTS, and libwebrtc's PacketBuffer cannot assemble the result. The browser dropped roughly 60% of frames at the decode stage on a clean LAN with zero packet loss (framesAssembledFromMultiplePackets 39.7%, versus 99.9% on the VA path). The stream looks black or frozen while video.videoWidth is set and currentTime advances, so it is easy to misread as a negotiation problem.

The RGBx and DMABuf output paths never hit this because each builds a fresh GstBuffer (PTS NONE) every frame. This restores the same behaviour for the Vulkan path: clear PTS/DTS/duration on the recycled buffer before returning it, so do_timestamp re-stamps it with the current running time each frame.

Scoped to the encode_src case, so the compositor-NV12 dmabuf path (encode_src == false) is byte-identical. Only timing metadata is reset — the buffer's memory and video meta are untouched.

Build-verified on this branch's head (43d4c25). This fix has been running in my deployment since 2026-07-06.


🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/games-on-whales/gst-wayland-display/pull/45 **Author:** [@salty2011](https://github.com/salty2011) **Created:** 7/26/2026 **Status:** ✅ Merged **Merged:** 8/16/2026 **Merged by:** [@JBailes](https://github.com/JBailes) **Base:** `feat/vulkan-encode` ← **Head:** `fix/vulkan-encode-src-pts` --- ### 📝 Commits (2) - [`35da978`](https://github.com/games-on-whales/gst-wayland-display/commit/35da9788671a582eee24b8a69876116701e794a2) fix(vulkan): clear PTS on recycled encode-src ring buffers so do_timestamp restamps - [`7853a24`](https://github.com/games-on-whales/gst-wayland-display/commit/7853a248274e03dfe118acf208892daf60eba576) review: move PTS reset into convert_inner after the reuse gate ### 📊 Changes **1 file changed** (+27 additions, -0 deletions) <details> <summary>View changed files</summary> 📝 `wayland-display-core/src/utils/vulkan_nv12.rs` (+27 -0) </details> ### 📄 Description `VulkanNv12::to_gst_buffer()` returns a bare clone of the current ring slot's persistent `GstBuffer`. `waylanddisplaysrc` runs with `set_do_timestamp(true)`, which only stamps a buffer whose PTS is `GST_CLOCK_TIME_NONE` — and a recycled slot buffer still carries the PTS from its previous use, so `do_timestamp` skips it. With the default ring depth of 4, the exported PTS therefore degenerate to four recurring values, non-monotonic and duplicated across frames. Live trace on my host: **99.9% of frames shared a timestamp with another frame, 25% were non-monotonic, and exactly four distinct RTP timestamps cycled forever.** Downstream that is fatal for WebRTC: `rtph264pay` derives RTP timestamps from those PTS, and libwebrtc's `PacketBuffer` cannot assemble the result. The browser dropped roughly **60% of frames at the decode stage** on a clean LAN with zero packet loss (`framesAssembledFromMultiplePackets` 39.7%, versus 99.9% on the VA path). The stream looks black or frozen while `video.videoWidth` is set and `currentTime` advances, so it is easy to misread as a negotiation problem. The RGBx and DMABuf output paths never hit this because each builds a fresh `GstBuffer` (PTS `NONE`) every frame. This restores the same behaviour for the Vulkan path: clear PTS/DTS/duration on the recycled buffer before returning it, so `do_timestamp` re-stamps it with the current running time each frame. Scoped to the `encode_src` case, so the compositor-NV12 dmabuf path (`encode_src == false`) is byte-identical. Only timing metadata is reset — the buffer's memory and video meta are untouched. Build-verified on this branch's head (`43d4c25`). This fix has been running in my deployment since 2026-07-06. --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
bsakaguchi 2026-10-15 12:47:54 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
games-on-whales/gst-wayland-display#48
No description provided.