Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion quest/m1/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ moves what remains of them once their claims merge.
- [Session policy lives in moq-net](/quest/m1/session-policy/README.md) - accept and connect deadlines, admission, window widening and reconnect live once in moq-net; moq-tokio and moq-relay's io_uring path call them
- [Vendor and trim the WebRTC stack](/quest/m1/webrtc-vendor.md) - str0m, dimpl, `is`, and sctp-proto live in moq-webrtc with unused code removed, so moq-webrtc can take rind
- [MoQ on rind](/quest/m1/rind/README.md) - every MoQ crate takes its crypto from rind, a pure-Rust graviola fork, so no build compiles C crypto
- [VA-API encode is correct on radeonsi](/quest/m1/vaapi-radeonsi.md) - AMD's VA-API H.264 encode decodes, or the node is refused for OpenH264
- [VA-API encode is correct on radeonsi](/quest/m1/vaapi-radeonsi.md) - AMD's VA-API H.264 encode decodes, once moq takes moq-vaapi 0.2.1
- [Tests run on a mocked clock](/quest/m1/mock-clock-tests/README.md) - about 300 tests stop proving nothing happened by waiting, sleeping to settle, or asserting on elapsed time
- [moq-mux reads H.265 SPS without scuffle](/quest/m1/h265-sps-reader.md) - moq-mux's own SPS reader replaces scuffle-h265 and scuffle-expgolomb, and the fuzz regressions still pass
- [QMux reads the app-limited flag on big-endian Linux](/quest/m1/qmux-app-limited-endian.md) - the send-rate filter's app-limited mask follows the target's byte order
Expand Down
73 changes: 29 additions & 44 deletions quest/m1/vaapi-radeonsi.md
Original file line number Diff line number Diff line change
@@ -1,56 +1,41 @@
# [M] VA-API encode is correct on radeonsi
# [S] VA-API encode is correct on radeonsi

## Goal

On an AMD RX 9070 (radeonsi), moq-video's VA-API H.264 encoder either
produces a stream that ffmpeg decodes, or refuses the node, so `Kind::Auto`
falls to the next H.264 encoder (OpenH264 in a build that has it; a build
without one gets `NoEncoder` naming the refused driver). Its VPP NV12 conversion carries no chroma offset, and its
rate control stays near the target bitrate. The ignored VA-API encode tests
in `rs/moq-video/src/encode/backend/vaapi.rs` pass on that card with
`MOQ_VAAPI_DEVICE` naming its node, or skip with a reason that names the
refused driver.
On an AMD RX 9070 (radeonsi), moq-video's VA-API H.264 encoder produces a
stream that ffmpeg decodes, its VPP NV12 conversion matches the space it
labels, and its rate control stays near the target bitrate. The VA-API
tests in `rs/moq-video/src/encode/backend/vaapi.rs`, ignored ones included,
pass on that card with `MOQ_VAAPI_DEVICE` naming its node.

## Plan

Found 2026-11-06 in [moq-dev/moq#8013](https://github.com/moq-dev/moq/pull/8013)'s
hardware run on an RX 9070 (Mesa 26.0.8, `renderD129`): 6 of 19 VA-API tests
failed, all of them H.264 encode. A 320x240 dump gives ffprobe
`Invalid data found when processing input`, and its first NAL unit has type
0. This also reproduces on main's moq-vaapi. H.265 encode and both decoders
pass there. [moq-dev/vaapi#10](https://github.com/moq-dev/vaapi/pull/10)
also noted a chroma offset in radeonsi's VPP NV12 output and a bitrate
overshoot.

Decided 2026-11-06 (maintainer, /quest-unblock): ✅ keep #8013 queued, which
puts `vaapi` on by default in moq-cli and moq-transcode, and fix this in m1.
Until it lands, an AMD-only host encodes H.264 through VA-API and publishes
a stream nobody can decode; moq-c and moq-ffi already did. Not chosen:
pulling #8013 to refuse radeonsi first, or keeping `vaapi` opt-in. Also
decided: ✅ find the root cause in m1. Not chosen: m3 beside
[Vulkan Video encode on AMD](/quest/m3/vulkan-encode.md), or only a note
there.

- Find whether the H.264 bytes are ours. NAL type 0 at the start points at
how moq-vaapi reads the coded buffer (a segment's `bit_offset`, or more
than one segment) or at packed headers radeonsi does not take for H.264.
[moq-dev/vaapi#10](https://github.com/moq-dev/vaapi/pull/10) had to
require packed H.265 parameter sets for the same reason. Compare against
`ffmpeg -c:v h264_vaapi` on the same node.
- If it is moq-vaapi's, fix it there with a test, release the crate, and bump
`moq-vaapi` here. If it is the driver's, refuse a radeonsi node for H.264
encode, using the driver's vendor string, so the candidate fails to open and
OpenH264 takes over. Then link the Mesa issue.
- Fix the chroma offset and the bitrate overshoot if they are ours. If the
chroma offset is the driver's VPP, skip VPP on radeonsi and convert to NV12
before upload. If the overshoot is the driver's, refuse a radeonsi node for
that encode, as for the H.264 bytes, so `Kind::Auto` moves on. Link the
Mesa issue either way.
- Vulkan Video still replaces VA-API on AMD later; this quest does not wait
on it.
The causes were in moq-vaapi and are fixed in
[moq-dev/vaapi#13](https://github.com/moq-dev/vaapi/pull/13). With it patched
in, all 19 of moq-video's VA-API tests pass on the RX 9070 (`renderD129`,
Mesa 26.2.5); on moq-vaapi 0.2.0, 7 fail. That PR's body has the evidence.

- H.264 bytes: radeonsi writes the packed SPS and PPS, and the slice's NAL
header, only from a packed slice header, which moq-vaapi did not send.
- Bitrate: moq-vaapi's QP ceiling of 36 set a smallest picture on both iHD
and radeonsi; it is now 51.
- Chroma: not an offset. Mesa's VPP reads the BT.601 standard as SMPTE 170M
primaries and gamut-maps; moq-vaapi now names each side explicitly on Mesa.

What remains here: bump `moq-vaapi` in the root `Cargo.toml` to the release
with #13, refresh `Cargo.lock` with it, and say in the module docs of
`rs/moq-video/src/encode/backend/vaapi.rs` that the tests pass on radeonsi.
Then delete this quest.
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Resolved

Public API: none. Wire: none.

## Waiting

- Maintainer: merge [moq-dev/vaapi#13](https://github.com/moq-dev/vaapi/pull/13)
and publish it as moq-vaapi 0.2.1 (a patch: no public API change). Version
bumps are a person's call, so an agent does not cut the release. Check that
`cargo info moq-vaapi@0.2.1` finds it.

## Related

- [Vulkan Video encode on AMD](/quest/m3/vulkan-encode.md) - AMD's long-term encode path
Expand Down
Loading