5.8 KiB
effectcraft-hevcenc
Clean-room, pure-Rust HEVC / H.265 encoder for EffectCraft's MP4 export (layer L0, std only,
no unsafe, builds for wasm32-unknown-unknown).
What it produces
- Profiles: Main (8-bit) and Main 10 (10-bit), 4:2:0, Main tier.
general_level_idcis taken from the config or chosen as the lowest level whose MaxLumaPs, MaxLumaSr (and, in bitrate mode, MaxBR) fit (Table A.8). - Parameter sets: VPS, SPS (with VUI: BT.709 colour description,
video_full_range_flag, timing info from the frame rate) and PPS, as raw NAL units (Encoder::parameter_sets) and as anhvcCrecord (ISO/IEC 14496-15 §8.3.3.1,lengthSizeMinusOne3, complete VPS / SPS / PPS arrays,Encoder::hvcc). - Pictures: one slice per picture;
IDR_N_LPeverykeyintpictures (1= all intra,0= only the first),TRAIL_RP pictures otherwise, each referencing the previous picture (one short-term RPS in the SPS,num_ref_idx_l0_active1, no reordering, pts = dts). Packets are length-prefixed (4-byte big-endian) NAL units without parameter sets. - Picture size: any even width / height; the coded size is padded to a multiple of 8 by edge
replication and cropped with the conformance window. Odd sizes are rejected with
Error::InvalidConfig(4:2:0 conformance-window offsets are in units of two luma samples).
Coding tools
- 64x64 CTUs, coding units 64x64 .. 8x8 chosen by rate-distortion optimisation: every candidate is actually predicted, transformed, quantised and reconstructed, and its rate is measured with a CABAC bit estimator that evolves the same context states as the real coder. Split decisions compare the best unsplit candidate with the recursively coded children (early exit after a skip).
- Intra: all 35 modes (SATD search on a coarse grid plus refinement and the MPMs), 2Nx2N at 8..32 and NxN (four 4x4 PUs) at 8x8, chroma in DM mode, MPM / remaining-mode coding, reference substitution, [1 2 1] and strong (32x32) smoothing, DC / angular boundary filters.
- Inter (P): skip and merge (spatial candidates + zero candidates,
MaxNumMergeCand5) and AMVP with mvd coding; integer motion search (predictor starts + square pattern, steps 16..1) and half / quarter-sample refinement on pre-interpolated half-sample planes; the coded prediction uses the normative 8-tap / 4-tap interpolation filters and reference-picture edge clamping. - Transforms: DST-VII 4x4 (intra luma) and DCT 4..32 (inverse by even/odd decomposition,
bit-identical to the matrix form), dead-zone quantisation (1/3 intra, 1/6 inter), flat scaling,
sign data hiding, inferred transform splits only (
max_transform_hierarchy_depth_*0, so 64x64 CUs use four 32x32 TUs). - Entropy coding: CABAC (context initialisation by slice QP and init type, decision / bypass /
terminate bins, flush),
end_of_slice_segment_flag, byte alignment, emulation prevention. - In-loop filters: the deblocking filter is on (the encoder deblocks its own reconstruction, so references match the decoder); SAO is disabled.
- Rate control:
ConstantQp(qp)orBitrate { kbps }, a per-picture QP from a bits-x-Qstep model per picture type (I pictures get roughly 4x the bits of a P picture) with a buffer that spreads over- and undershoot over the following pictures.
Not implemented: B pictures / reordering, multiple references, TMVP, AMP and other inter partition shapes, residual quadtree splits, transform skip, scaling lists, PCM, SAO, RDOQ, cu_qp_delta / adaptive quantisation, tiles / WPP / multiple slices, range extensions (4:2:2, 4:4:4, > 10 bits).
Measurements
On a shared, heavily loaded machine, opt-level 3: about 0.45 s of CPU per 1920x1080 picture
(ffmpeg testsrc2, QP 22 / 32). On ffmpeg's mandelbrot 1080p source (8 pictures, IPPP, QP 32)
the stream is about 12 % larger at about 0.2 dB lower mean PSNR-Y than x265 --preset medium at
the same QP without psy tuning (110.5 kB / 42.3 dB vs 98.3 kB / 42.5 dB). The synthetic test image
reaches 45.8 dB PSNR-Y at QP 22.
Tests
cargo test -p effectcraft-hevcenc:
- every stream is decoded with the first-party
filmcraft-hevcdecoder and compared bit-exactly with the encoder's reconstruction (Encoder::last_reconstruction, hidden API); - when
ffmpegis onPATH, the Annex-B elementary stream is decoded withffmpeg -v error -xerror(no stderr output allowed) and compared bit-exactly as well (skipped otherwise). ffmpeg is used only as an external test oracle; - covered: 8-bit and 10-bit, all-intra and IP, QP 0 noise (escape codes), QP 0..51, strong
deblocking at high QP, sizes 8x8 .. 200x136 with cropping, POC wrap (300 pictures without IDR),
bitrate mode within 2x of the target,
hvcClayout; bench_1080p(ignored) reports speed, size and PSNR on 1080p content generated by ffmpeg.
Specifications
- ITU-T H.265 (V8, 08/2021) | ISO/IEC 23008-2, High efficiency video coding: 7 (syntax and semantics), 8.4 - 8.7 (intra / inter prediction, scaling and transforms, deblocking), 9.3 (CABAC, including the informative encoder description of 9.3.4), Annex A (profiles, tiers and levels), Annex E (VUI).
- ISO/IEC 14496-15 (2019), §8.3.3.1 HEVCDecoderConfigurationRecord.
Implemented from the specification text. Constant tables (CABAC context layout and initValues,
rangeTabLPS / transIdx, scan orders, the DCT / DST matrices, intra angles, interpolation filters,
the chroma QP table, the deblocking beta / tC tables) and the decoder-side reconstruction
arithmetic (intra reference substitution / filtering / prediction, fractional interpolation,
deblocking) are mirrored from FilmCraft's first-party, spec-derived filmcraft-hevc decoder (same
organisation, MIT OR Apache-2.0), so that encoder and decoder reconstruct identically. No
third-party encoder or decoder source (x265, libde265, ffmpeg, HM, ...) was consulted.