feat(hwdec): VAAPI backend — HEVC Main/Main10 + AV1 still decode over dlopen'd libva - #51
Merged
Merged
Conversation
… dlopen'd libva Implements the Linux hardware decode backend behind rawshift-hwdec's safe API. libva.so.2/libva-drm.so.2 are dlopen'd at runtime via libloading with a hand-written minimal FFI surface (~26 entry points): no link-time libva dependency, and a missing library, render node, or driver degrades to decoder() == None — headless-safe by construction. Every FFI struct layout is transcribed from the system va*.h headers and pinned by unit tests asserting size_of/offset_of against gcc-computed values. HEVC Main and Main10: hvcC NAL-array parsing (in-crate — the FFI crate takes raw hvcC bytes and has no gamut-heic dependency; upstream Annex-B helpers remain gamut#255), full SPS/PPS and IRAP I-slice header parsing in safe Rust, VA picture/slice parameter submission, still-picture scope (IDR/CRA single frame) with clear Decode errors outside it. AV1 Profile0: av1C + OBU framing, sequence and intra frame header parse including tile info, film grain (second display surface), CDEF, and loop restoration. 8-bit surfaces read back as Nv12, 10-bit as P010, honouring driver pitches and cropping to owned planes. available_codecs() answers from real vaQueryConfigProfiles. Unsafe stays confined to the FFI boundary per PRINCIPLES.md: bit-level parsers are 100% safe Rust; every unsafe block carries a SAFETY comment (34 blocks across vaapi/mod.rs + sys.rs, grep-audited). NVIDIA support via nvidia-vaapi-driver is documented per docs/SUPPORT.md. Verified on real hardware (AMD RX 7900 XT, Mesa radeonsi): device-gated tests decode real x265 Main (NV12), Main10 (P010), and libaom AV1 (NV12) bitstreams, and the end-to-end path HeicFile::decode_primary -> gamut-heic -> VAAPI -> RgbImage passes with real pixel statistics, including a hardware-decoded HEIC thumbnail. All device tests skip gracefully without a device, keeping CI green. Upstream: filed visualcommons/gamut#304 (decode_item_rgba8 rejects items carrying both ICC and nclx colr — the shape of real iPhone files); the HDR presentation gap remains gamut#303 (Main10 decode works; 10-bit RGB presentation waits upstream).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #29.
Stacked on #50; merge order #42 → #44 → #45 → #46 → #47 → #48 → #49 → #50 → this.
What is Delivered
libva.so.2/libva-drm.so.2load at runtime vialibloadingbehind a hand-written ~26-entry-point FFI surface. Missing library/render-node/driver →decoder() == None, never a link failure — headless-safe by construction (lddon the test binary shows no libva). Every FFI struct layout is transcribed from the systemva*.hheaders and pinned by tests assertingsize_of/offset_ofagainst gcc-computed values (e.g.VAPictureParameterBufferHEVC= 604 B).Decodeerrors outside it (documented on the module).DecodedFrame, honouring driver pitches, cropping to owned planes.available_codecs()answers from realvaQueryConfigProfiles.// SAFETY:comment (grep-audited).#![deny(unsafe_op_in_unsafe_fn)], all public items safe. NVIDIA-via-nvidia-vaapi-driverdocumented perdocs/SUPPORT.md.Verification Done — on real hardware
Host: AMD RX 7900 XT (Mesa radeonsi, libva 2.23). Run independently after implementation:
cargo test -p rawshift-hwdec --features vaapi— 38/0, device tests ran (not skipped): real x265 Main→NV12, Main10→P010, real libaom AV1→NV12 bitstream decodes with pixel-variance assertions, probe consistency, garbage-bitstream rejection.heic_primary_hw_decodes_end_to_end_with_real_pixelsandheic_thumbnail_hw_decodes_when_listedpass —HeicFile::decode_primary→ gamut-heic → VAAPI →RgbImagewith real pixel statistics.-p rawshift-image --features full— 542/0.cargo test --workspace— 387/0 (stub config: 9 hwdec tests, device tests compile out). Clippy-D warnings×3 configs — all clean. Stub/hw/release builds clean. Device tests skip gracefully without hardware → CI stays green.Upstream
Filed gamut#304 during this work (
decode_item_rgba8rejects items carrying both ICC and nclxcolr— the shape of real iPhone files). HDR presentation remains gamut#303: Main10→P010 decode works and is device-tested here; 10-bit RGB presentation waits upstream. SDR HEIC is now hardware-decoded end-to-end.