89 lines
5.8 KiB
Markdown
89 lines
5.8 KiB
Markdown
# 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_idc` is 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 an
|
|
`hvcC` record (ISO/IEC 14496-15 §8.3.3.1, `lengthSizeMinusOne` 3, complete VPS / SPS / PPS
|
|
arrays, `Encoder::hvcc`).
|
|
- **Pictures:** one slice per picture; `IDR_N_LP` every `keyint` pictures (`1` = all intra, `0` =
|
|
only the first), `TRAIL_R` P pictures otherwise, each referencing the previous picture (one
|
|
short-term RPS in the SPS, `num_ref_idx_l0_active` 1, 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, `MaxNumMergeCand` 5) 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)` or `Bitrate { 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-hevc` decoder and compared bit-exactly
|
|
with the encoder's reconstruction (`Encoder::last_reconstruction`, hidden API);
|
|
- when `ffmpeg` is on `PATH`, the Annex-B elementary stream is decoded with
|
|
`ffmpeg -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, `hvcC` layout;
|
|
- `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.
|