forked from unom/punktfunk
The H.265 twin of plan_to_va, and with it pf-vaadec covers both codecs end to end from an AuPlan to the buffers a vaRenderPicture call carries. What remains for the rung is the Linux-only plumbing. HEVC differs from H.264 in four ways that each had to be got right rather than assumed, and they are why this is a separate module instead of a parameter: ReferenceFrames is 15 entries, not 16. The reference sets are FLAGS, not arrays. There is no RefPicSetStCurrBefore here: membership is ORed into each DPB entry's own flags. Vulkan wants slot indices in identically named arrays, DXVA wants list positions in them, and VAAPI wants neither — three spellings of one idea, and confusing the first two is what made HEVC unplayable on every driver. The per-slice lists are INDICES into ReferenceFrames, not pictures and not surfaces. So the DPB array is built first and every list entry resolved through it; a picture a slice names that is not in the marked DPB is a refusal rather than something to paper over, because there is nothing to fall back to. The offset is in BYTES. slice_data() is byte-aligned by byte_alignment(), so header_bit_size / 8 is exact — and a header that is not a whole number of bytes is an error rather than a rounded offset, which would decode garbage from the first inter picture. Two conversions that are NOT copies, and would have been silently wrong as copies: libva takes the derived ChromaOffsetLX (equation 7-56) where the parser stores the coded delta, so putting the delta there would tint every weighted-predicted block; and only 32x32 matrixIds 0 and 3 exist, where the parser keeps six slots. The IQ matrix is Optional and gated on scaling_list_enabled_flag for the reason review round 13 found on the DXVA side — a driver MUST apply what it is handed, so a table of parser defaults dequantises every residual to zero. The weight table is only filled where 7.3.6.1 says one is coded, and the chroma denominator is clamped into a legal shift so a malformed stream cannot panic a decode thread. Tests walk both HEVC vectors — the 250-frame 8-bit one and the 50-frame Main 10 one, so a depth field wired to a constant would show — asserting per slice that the start code was trimmed, the byte offset is inside the slice, and every used list index points at a DPB entry that is actually valid. Per picture it asserts that exactly the three current sets carry RPS flags and nothing else does, and the walk fails if it never saw an RPS flag or a reference at all, so it cannot pass vacuously.