Files
effectcraft/crates/vp9enc/README.md
T
Brandon ThomasandClaude Opus 5.5 b26fbb6247 M10.2: VP9 inter frames (motion search, MV prediction, loop filter, forward probability updates, rate control)
effectcraft-vp9enc gains inter frames: single LAST reference, 16x16/8x8 blocks,
candidate + diamond search refined to quarter samples with the regular 8-tap
filters, NEARESTMV/NEARMV/ZEROMV/NEWMV with spec MV prediction, skip blocks,
the in-loop deblocking filter, per-frame forward probability updates, a key
frame interval and target-bitrate rate control. Decoded output matches the
encoder's reconstruction exactly through FilmCraft's decoder and ffmpeg.
WebM export now encodes sequentially with a key frame every two seconds.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-03 03:44:03 -04:00

3.7 KiB
Raw Blame History

effectcraft-vp9enc

A small VP9 encoder for WebM export (profile 0, 8-bit 4:2:0, BT.709).

  • Key frames: 8×8 intra blocks (DC / V / H / TM prediction chosen per block), 4×4 DCT/ADST transforms, or the Walsh–Hadamard transform at quality 100 (mathematically lossless).
  • Inter frames: one reference (the previous frame, LAST), 16×16 or 8×8 blocks chosen by a cost comparison; motion search from the predicted vectors (NearestMv / NearMv / last frame's co-located vector) with a whole-sample cross/diamond search refined to half and quarter samples with the regular 8-tap interpolation filters; NEARESTMV / NEARMV / ZEROMV / NEWMV chosen by bit cost; blocks with no coefficients worth coding are skipped; 4×4 DCT residual with a rate–distortion check per transform block. Inter frames are coded error resilient (error_resilient_mode = 1: no dependence on earlier probability contexts or motion vectors), so UsePrevFrameMvs is never needed. No high-precision (1/8) vectors, no compound prediction, no intra blocks inside inter frames.
  • Loop filter: the in-loop deblocking filter (§8.8) on every lossy frame; the level is the best of three trials against the source (sharpness 0, no mode/reference deltas).
  • Probabilities: per-frame forward updates in the compressed header (diff_update_prob / update_mv_prob) of the coefficient, skip, inter-mode, is-inter, reference, partition and motion-vector probabilities. Tiles are recorded as symbols first, the frame's own counts pick the updates that pay for their signalling, then the symbols are entropy coded with the updated probabilities. There is no backward adaptation (refresh_frame_context = 0).
  • Rate control: constant quality (quality → base_q_idx) or a target bitrate: a per-frame q index from a bits ≈ complexity / step model per frame type, key frames getting a larger share of each key-frame interval, with the running over/undershoot paid back over about a second.
  • Key frame interval is configurable (1 = every frame a key frame, the old intra-only mode).

The encoder reconstructs exactly what a decoder reconstructs (inter prediction with the decoder's vector clamping and edge-clamped reference fetches, integer inverse transforms, the loop filter) and exposes it (Vp9Encoder::reconstruction); the tests require FilmCraft's VP9 decoder (and ffmpeg, when installed) to output exactly that reconstruction, frame by frame, for moving synthetic sequences at several sizes and qualities, with tile columns, and lossless.

On a moving-gradient sequence (192×108, 24 frames) inter coding is 3.9–7× smaller than all-intra at the same quality setting with equal or better PSNR.

Written from the VP9 Bitstream & Decoding Process Specification, version 0.6 (31 March 2016): the encoder emits the uncompressed and compressed headers (§6.2, §6.3), partition, mode info, motion vector and token syntax (§6.4), derives motion vector candidates with the §6.4 find_mv_refs / find_best_ref_mvs processes, and reconstructs with the specification's intra and inter prediction (§8.5), integer inverse transforms (§8.7) and loop filter (§8.8) so it stays in step with any conformant decoder. The boolean encoder is the inverse of the §9.2 decoder in the form given in RFC 6386 §7.3. Spec tables (§10) are the specification's; the key-frame tables were transcribed from FilmCraft's first-party decoder filmcraft-vp9 (MIT OR Apache-2.0), which is also the decoder the tests round-trip through and whose behaviour (loop filter edge rules, vector candidate order) the encoder was checked against; ffmpeg is used only as an external test oracle. No libvpx or other third-party encoder/decoder source was consulted.