Skip to content

perf(ps5): low-latency decoder instance; decode and render wait measured apart - #129

Open
xservzeroman wants to merge 2 commits into
feat/ps5-bitrate-100from
perf/ps5-decode-latency
Open

xservzeroman wants to merge 2 commits into
feat/ps5-bitrate-100from
perf/ps5-decode-latency

Conversation

@xservzeroman

@xservzeroman xservzeroman commented Oct 24, 2026 •

Copy link
Copy Markdown

Stacked on #128. Submodule third-party/chiaki-ng points at chiaki-ng-mooncast perf/decode-latency @ 227e79dd (two commits on top of c5fa7fad).

Saleh: PXPlay shows decode < 1 ms on the Odin 2 Portal (Snapdragon 8 Gen 2, "kalama"); MoonCast showed up to 5 ms on the same device and network.

What the numbers measured

  • MoonCast before: queued to MediaCodec → output buffer dequeued, but taken after the frame was handed to the screen (releaseOutputBuffer / …AtTime), smoothed over about 20 frames.
  • PXPlay most likely measures queued → output available.

What I found on the Odin

  • The device has c2.qti.hevc.decoder and c2.qti.hevc.decoder.low_latency (also AVC). createDecoderByType always picked the default one.
  • The low-latency instance accepts all our keys (level 0). On a mostly still PS5 home screen, though, it only saved about 0.2 ms over the default.
  • Diagnostics: frames were ~600–2000 bytes. Feeding a frame (dequeue input + copy + queue) takes 0.4–0.6 ms, so the codec2 pipeline itself costs ~2–3 ms even for tiny frames.
  • A plain releaseOutputBuffer(render) never fired the frame-rendered callback on this codec2 decoder. Releasing with a timestamp (now) does, and shows the frame just as soon.

Changes (chiaki-ng-mooncast fd5b9a23 + 227e79dd)

  1. Decoder Low / Ultra use the <name>.low_latency (Qualcomm) or .lowlatency (MediaTek) instance when the device has one. Standard keeps the default.
  2. Qualcomm: operating-rate 32767.
  3. Output thread at priority -8 (logged: "output thread at priority -8").
  4. Decode = queued → decoded, measured before release.
  5. New render wait = decoded → on screen, via AMediaCodec_setOnFrameRenderedCallback (Android 13+). Lowest delay now releases with releaseOutputBufferAtTime(now) so it reports.
  6. Both are shown in Detailed stats ("decode (queued to decoded)", "render wait (decoded to on screen)") and logged as stats … decode= render=. A diagnostics line is logged every 1800 frames.

Measurements (Odin 2 Portal, PS5-423, 1080p60 HEVC, home screen ~0.3 Mbps, 30 s each, test268)

Decoder Frame pacing decoder instance decode render wait
Standard Lowest delay c2.qti.hevc.decoder 3.92 ms 0.20 ms
Low Lowest delay .low_latency 3.72 ms 0.22 ms
Ultra Lowest delay .low_latency + sw fences 2.77 ms 0.22 ms
Low Balanced .low_latency 3.67 ms 7.40 ms
Low Smoothest .low_latency 3.65 ms 12.33 ms
Ultra Balanced .low_latency 2.78 ms 8.30 ms
  • Before: test237 (2026-10-21) measured 7.4 / 8.5 / 9.0 ms, and Saleh saw "up to 5 ms". Both counted the release-to-screen step inside "decode".
  • Biggest real delay: Frame pacing. Saleh's Odin was set to Smoothest, which adds ~12 ms. Lowest delay adds ~0.2 ms.
  • Not reached: sub-1 ms decode. On this device the codec2 path seems to have a ~2.5–3.5 ms floor even for tiny frames. PXPlay's "< 1 ms" may start its clock later (e.g. after queueInputBuffer returns, which alone is ~0.5 ms here) or use a different measure; we can't see its code.
  • Not measured: a high-bitrate moving game. All runs were on the PS5 home screen.

Test notes

  • The Odin was driven over adb with Saleh's OK: PS5-423 woken and streamed, then put back in rest via the Quick menu.
  • The Odin's MoonCast settings were backed up and restored (checksum identical), and it's back on its launcher.
  • test268 (final, 67ce10f) is installed on the Odin.

🤖 Generated with Claude Code

xservzeroman and others added 2 commits October 24, 2026 20:07
…red apart

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… changelog

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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.

1 participant