Repository navigation
feat(decode)!: H.265 Main decode beside H.264 - #11
Merged
Merged
Conversation
`decode::Config` gains `codec`, and `Decoder` dispatches to an H.265 decoder ported from discord/cros-codecs's stateless H.265 decoder, with its parser, DPB, and picture modules vendored beside the H.264 ones. It derives reference picture sets (8.3.2) and reference lists (8.3.4), bumps the DPB by the SPS's reorder limit (C.5.2), so a stream with no B-frames comes out as it decodes, skips RASL pictures after a CRA that starts the stream over, and handles dependent slice segments. Screen content and range extensions are left out; Main, plus Main 10 and Main Still Picture streams that hold 8-bit samples, 4:2:0, right/bottom crop. The two decoders share the VA side: a sequence is keyed on a `Format` (codec, VA profile, coded and visible size, DPB size), and submitting a picture goes through one helper. `probe` takes the codec it checks for. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Keep every slice entry point: a 4K picture with wavefronts signals 33 at 64-pixel CTBs, past the 32 a fixed array held. - Read a sublayer's profile on its profile-present flag and its level on its level-present flag, rather than both on the level flag. - Size the tile arrays for the inferred last column and row, and refuse more tiles than any level allows. - Count a picture's output latency against SpsMaxLatencyPictures, the reorder limit plus sps_max_latency_increase_plus1 minus one (C.5.2.2). - Refuse a field-coded sequence instead of putting each field out as a frame. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Twenty columns by twenty-two rows of tiles now parse, and their product overflowed the u8 counts it was taken in. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
kixelated
marked this pull request as ready for review
November 6, 2026 09:25
|
Warning Review limit reachedYou've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. Next included review available in 59 minutes. View limit details
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. |
# Conflicts: # Cargo.toml # README.md # src/codec.rs
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.
Part of the moq-video VAAPI quest, moq-dev/moq#8013, which wires this into moq-video's VAAPI decode backend.
Stacked on moq-dev/vaapi#9: the first commit here is #9's, so review
efb73fb,38dfca1, andd1c7c3aalone until #9 lands.Problem
The decoder handles H.264 only, so an H.265 broadcast falls back to software decode in moq-video even on hardware that decodes H.265.
Approach
decode::Configgainscodec, H.264 unless set.Decoderdispatches to the existing H.264 decoder or a new H.265 one insrc/decode/h265.rs.codec::h265. It derives each picture's reference picture set (8.3.2) and each slice's reference lists (8.3.4), skips RASL pictures after a CRA that starts the stream over, and handles dependent slice segments.Format(codec, VA profile, coded and visible size, DPB size), and a picture is submitted through one helper.field_seq_flag) is refused, since its pictures would come out as unpaired fields.Impact
decode::probetakes the codec it checks for.decode::Confighas a new public field, so a struct literal without..Config::new()no longer compiles.decode::Config::codec, andCodecat the crate root (the same enum moq-dev/vaapi#10 adds for encode; whichever lands second resolves a one-line conflict incodec.rs, the README, and the Cargo description).Validation
On Intel Arrow Lake (iHD 26.1.2) and AMD Radeon RX 9070 (radeonsi, Mesa 26.0.8),
just ci(fmt, clippy, tests, docs, cargo-deny) and the full test suite. The AMD run pointed the decoder at its render node for the run only.decoded_pictures_match_a_software_decodernow covers both codecs, coded by x264 and x265 with two B-frames and three references, at 320x240 and cropped at 852x478. Every picture matches ffmpeg's software decode bit for bit, comes out reordered, and keeps its timestamp. The x265 stream has an IDR and an open-GOP CRA. Half the pictures go throughdecode_exportedanddownload.h265_without_reordering_comes_out_as_it_decodesdecodes an x265 stream with no B-frames and checks each call returns its own picture.a_new_h265_sequence_decodes_at_its_own_sizeconcatenates two x265 streams at different sizes and checks the first one's tail comes out ahead of the second, at the right size.a_4k_h265_wavefront_stream_decodesdecodes a 3840x2160 x265 stream with wavefronts and 64-pixel CTBs, whose slices carry more than 32 entry points.Alternatives
H265Decodertype: two public decoders with identical methods, where moq-video would pick one from the catalog's codec anyway.Follow-ups
Review
Codex (
quest review, gpt-6.1-sol, medium), three rounds against #9's headdba9a75.efb73fb, five findings, all fixed in38dfca1: entry point offsets overflowing a 32-entry array on 4K wavefront input; sublayer profiles gated on the wrong flag; the inferred last tile column or row overflowing its array; the latency limit compared against the wrong threshold; field-coded sequences accepted.38dfca1, one finding, fixed ind1c7c3a: the entry point bound multiplied the tile counts asu8, which overflows at 20x22 tiles.d1c7c3a: no findings.(Written by Claude Opus 5.5)
🤖 Generated with Claude Code