Add ProRes 422 parser layer to oximedia-codec#20
Open
vbasky wants to merge 1 commit into
Open
Conversation
cool-japan
added a commit
that referenced
this pull request
May 19, 2026
Add `prores` Cargo feature flag to oximedia-codec; gate the prores module and re-export its public types behind it, consistent with the existing pattern for av1/vp9/vp8/mjpeg/apv feature-gated codecs. ProRes 422 parser (SMPTE RDD 36-2015) + full decode pipeline (entropy, dequant, IDCT) implemented in PR #20/#21 by vbasky; not on the project Green List but decoding is unencumbered in practice (FFmpeg ships it since 2010 without consequence). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
cool-japan
added a commit
that referenced
this pull request
May 19, 2026
- Mark AutoCaption pipeline (Wave 2 Slice C) as complete - Mark oximedia-neural oxionnx wiring (Wave 4 Slice D) as complete - Add 0.1.7 PR integration log: #18 RTSP, #22 FLV, #23 Windows, #20/#21 ProRes; note PR #19 HW-accel deferred to 2027+ Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
First half of Apple ProRes 422 decode support. Implements the
bitstream syntax defined in SMPTE RDD 36-2015 ("Apple ProRes
Bitstream Syntax") up to but not including entropy decode + IDCT.
Module: oximedia_codec::prores
ProRes is an intra-only 4:2:2 10-bit codec widely used as a
post-production intermediate. Patent licensing for encoding is held
by Apple; decoding is unencumbered in practice — FFmpeg has shipped
a decoder since 2010 without consequence.
Phase 1 (this revision) — parser + scaffolding
- frame.rs: Frame container parsing (4-byte size + 'icpf' marker)
and frame header parsing. Recognises every profile FourCC (apco /
apcs / apcn / apch / ap4h / ap4x), both chroma formats (4:2:2 /
4:4:4), all three interlace modes, custom and default quant
matrices, alpha-channel detection.
- picture.rs: Picture header and per-slice header parsing. Slice
header carries the quantization scale plus three (or four, with
alpha) compressed plane sizes that bound the slice's data region.
- quant.rs: Default 8x8 luma and chroma quantization matrices from
RDD 36 §6.5.4 Table 10, with tests pinning the spec invariants
(DC quantizer = 4; chroma HF > luma HF; diagonal monotonicity).
- bitreader.rs: MSB-first bit-level reader for the entropy stage.
Supports read_bits(1..=32), read_bit, count_leading_ones (for
unary prefixes of exp-Golomb codes), align_to_byte. Byte-boundary
handling, out-of-input errors, and >32-bit guard are all tested.
- decode.rs::split_slice_planes: Fully implemented helper that takes
the post-header bytes of a slice and the sizes from SliceHeader
and returns SliceData { luma, cb, cr, alpha } per-plane sub-slices.
This is the last step before entropy decode and catches truncated
streams / bit-flip corruption at slice boundaries.
Phase 2 extension point
decode::decode_slice_to_yuv422 has a stable signature, docstring,
and structured I/O — the function body returns
DecodeError::NotImplemented so callers fail loudly rather than
silently producing zeros. A test pins this contract so the public
surface can't accidentally drift into a no-op decoder.
The Phase 2 PR fills in:
1. Entropy decode (RDD 36 §6.5.5–6.5.6): DC differential coding +
AC run/level with adaptive Rice parameter.
2. Inverse zigzag scan (RDD 36 §6.5.7 Table 11).
3. Dequantization (coeff[i] = quantized[i] * matrix[i] * qscale).
4. 8×8 integer IDCT (RDD 36 §6.5.7).
5. Plane assembly to 10-bit YUV422 destination buffers.
Tests
34 unit tests covering: frame container parse + bad tag + truncated
buffer, frame header parse including every profile FourCC + version
guard + custom luma + custom luma+chroma matrices + interlace and
profile classification, picture header parse + trailing data, slice
header parse with and without alpha + truncated, default quant
matrix invariants, bit reader MSB-first single-bit + multi-bit +
zero-bit + too-many-bits + out-of-input + count_leading_ones +
align_to_byte, plane splitter with/without alpha + size mismatch,
and the Phase-2-stub-fails-loudly contract.
Build is warning-free and clippy-clean.
Out of scope
- Phase 2 decode pipeline (see decode.rs module doc).
- ProRes 4444 alpha-plane decode (parser already recognises it; the
IDCT + dequant + plane assembly will share Phase 2's machinery
once it lands).
- Encoder.
- Integration with oximedia_codec::VideoDecoder trait + CodecId::ProRes
variant — slot for that lands when the decoder is end-to-end.
06e9d34 to
3f4c059
Compare
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.
Description
First half of Apple ProRes 422 decode support — the parser layer up to but not including entropy decode + IDCT. Implements the bitstream syntax defined in SMPTE RDD 36-2015 ("Apple ProRes Bitstream Syntax").
ProRes is an intra-only 4:2:2 10-bit codec widely used as a post-production intermediate. Every video editor, colorist, and broadcast pipeline touches ProRes daily.
Module:
oximedia_codec::proresWhat's in Phase 1 (this PR)
frame.rs'icpf'marker). Frame header recognises every profile FourCC (apco/apcs/apcn/apch/ap4h/ap4x), both chroma formats (4:2:2 / 4:4:4), all three interlace modes, custom and default quant matrices, alpha-channel detection.picture.rsquant.rsbitreader.rsread_bits(1..=32),read_bit,count_leading_ones(for unary prefixes of exp-Golomb codes),align_to_byte. Byte-boundary handling, out-of-input errors, and >32-bit guard tested.decode.rs::split_slice_planesSliceHeaderand returnsSliceData { luma, cb, cr, alpha }per-plane sub-slices. Last step before entropy decode; catches truncated streams / bit-flip corruption at slice boundaries.Phase 2 extension point
decode::decode_slice_to_yuv422has a stable signature, docstring, and structured I/O — the function body returnsDecodeError::NotImplementedso callers fail loudly rather than silently producing zeros. A test pins this contract so the public surface can't accidentally drift into a no-op decoder.The Phase 2 PR fills in:
coeff[i] = quantized[i] * matrix[i] * qscale.Motivation
ProRes is one of the largest remaining FFmpeg-parity gaps that's actually closeable in pure Rust. Unlike H.264 / HEVC (multi-quarter projects), ProRes is intra-only, well-documented, and tractable — FFmpeg's
libavcodec/proresdec*.cis ~2K lines per component, and the bitstream is published as SMPTE RDD 36-2015.This PR lands the half that's safe to ship now (parsing — no pixel decode) so reviewers can audit the bitstream surface independently of the IDCT/entropy work. The decode pipeline can then be reviewed in isolation in a follow-up.
Fixes: no tracking issue — feature work.
Type of Change
Changes Made
crates/oximedia-codec/src/prores/:mod.rs,frame.rs,picture.rs,quant.rs,bitreader.rs,decode.rs.crates/oximedia-codec/src/lib.rsgains one line:pub mod prores;.Testing
Test Plan
Test Evidence
Locally on macOS aarch64:
The full workspace also builds clean with the prores module included.
Performance Impact
Checklist
Code Quality
cargo fmtandcargo clippycargo buildandcargo clippy --all-targets --no-deps)FrameError,DecodeError,BitReaderErrorenums viathiserror; nounwrap/expectin non-test code)Documentation
# Exampleblocks are deferred until Phase 2 when there's a usable end-to-end flow to demonstrate)Testing
oximedia-codecor other crates)unsafeblocks anywhere in the new code)Patent/Legal Compliance
Breaking Changes
Strictly additive — one new module, no existing API touched.
Dependencies
thiserrorwhich is already a workspace dependency)Additional Notes
Reviewer hint: the most consequential files to read are
frame.rs(the bulk of the parsing logic + profile enumeration) anddecode.rs(the documented Phase 2 extension point).quant.rsandbitreader.rsare short and self-contained.Out of scope (explicit follow-ups):
decode.rsmodule doc): entropy decode, inverse zigzag, dequantization, IDCT, plane assembly.oximedia_codec::VideoDecodertrait +CodecId::ProResvariant — that wiring lands when the decoder is end-to-end, not before.