ADR-1110: Add ΔE-ITP (Delta E ITP) — PQ-only HDR colour-difference CPU extractor¶
- Status: Accepted
- Date: 2026-06-14
- Deciders: Lusoris
- Tags: metric, feature-extractor, hdr, colour, fork-local
Context¶
The fork measures SDR colour difference (ciede, ΔE2000, hardcoded BT.709) and perceptual structure (ssimulacra2), but has no HDR / wide-colour-gamut colour-difference metric. ΔE-ITP (ITU-R BT.2124-0) is the ITU-standardised metric for assessing the visibility of colour differences in PQ and HLG HDR signals; adding it closes the WCG/HDR colour-fidelity gap.
ΔE-ITP is a fully analytic per-pixel metric (no trained model). It maps cleanly onto the existing VmafFeatureExtractor interface and mirrors the structure of ciede.c (per-pixel kernel, chroma upsampling, 8/16-bit reads, double-precision frame sum, mean pooling).
Two forces constrain the scope. First, VmafPicture carries no transfer-function or colorimetry metadata, so the extractor must assume a transfer function and primaries, exposed as options. Second, an adversarial verification of the dossier (.workingdir2/rc/metrics/deltae-itp.md) confirmed that the PQ pipeline — every matrix, the five PQ constants, the ITP scaling, the ×720 factor — is triple-sourced against the normative ITU-R BT.2124-0 PDF plus independent references, whereas the HLG (Annex 3) and BT.1886/SDR (Conversion 5) paths are single-sourced in BT.2124-0 itself and were not independently cross-validated.
Decision¶
We will add a CPU-only feature extractor delta_e_itp (provided feature key delta_e_itp) implementing the ITU-R BT.2124-0 Annex 1 ΔE-ITP pipeline for the PQ (SMPTE ST-2084) transfer function only. It exposes three string options — transfer (default pq; only pq accepted this release), matrix (bt2020 default / bt709), and range (limited default / full) — pools as the mean per-pixel ΔE-ITP, rejects 4:0:0 input with -EINVAL, and does all per-pixel math in double precision without clamping out-of-gamut LMS/ICtCp values. The HLG and BT.1886/SDR transfers are deferred follow-ups and are rejected with a clear error until their constants are independently validated.
Alternatives considered¶
| Option | Pros | Cons | Why not chosen |
|---|---|---|---|
| PQ-only ΔE-ITP now, defer HLG/SDR (chosen) | Every shipped constant is double/triple-confirmed; smallest correct surface; matches ciede/ssimulacra2 CPU-first staging | No HLG/SDR colour difference yet | Best risk/value: ships the verified HDR core without unvalidated constants |
| Ship all three transfers (PQ + HLG + BT.1886) now | One-shot complete BT.2124-0 coverage | HLG OOTF constants and the BT.709→BT.2100 primaries are single-sourced; risk of shipping an unverified number | Rejected — violates the fork's "every constant double-confirmed" bar |
Do nothing / rely on ciede for HDR | No new code | ciede is BT.709 SDR; produces meaningless numbers on PQ HDR | Rejected — leaves the WCG/HDR gap open |
Refuse to run without explicit transfer (no default) | No silent SDR-as-PQ mistakes | Worse UX; every invocation needs the flag; VmafPicture lacks the metadata to validate anyway | Rejected — transfer=pq default with a loud doc warning is the lighter contract |
Consequences¶
- Positive: the fork gains a standards-compliant HDR/WCG colour-difference metric; the per-pixel ITP triple is asserted against the BT.2124-0 normative oracle at places=4; no new dependencies or model assets.
- Negative: PQ-only — HLG and SDR HDR content are out of scope until a follow-up validates those constants. Feeding non-PQ content to the metric produces meaningless numbers (documented).
- Neutral / follow-ups: SIMD twins, GPU twins (target places=4–5, not bit-exact, per ADR-0220), a committed deterministic PQ LUT for byte-exact cross-host reproducibility, and the HLG / BT.1886 transfer options are all deferred follow-ups. The pre-existing stale
feature_extractor.c(dead twin of the live C++23feature_extractor.cpp, ADR-0846) is a maintenance trap surfaced during this work and should be removed separately.
References¶
- ITU-R BT.2124-0 (01/2019), Objective metric for the assessment of the potential visibility of colour differences in television — Annex 1 (normative pipeline: RGB→LMS, PQ EOTF, LMS'→ICtCp, ITP scaling, ΔE_ITP = 720·√Σ), Annex 4 (normative worked example: 58 % PQ blue ITP = [0.3554, 0.1346, -0.1613], ΔE = 2.363).
- ITU-R BT.2100 — RGB↔LMS integer matrix, PQ (ST-2084) transfer function, ICtCp definition.
- SMPTE ST 2084:2014 — PQ EOTF.
- Verified design dossier:
.workingdir2/rc/metrics/deltae-itp.md(adversarial verdict: GO-WITH-FIXES; all constants triple-sourced; required fixes — assert the full-precision ITP triple at places=4 instead of the pre-rounded 2.363, and ship PQ-only — applied). - In-tree pattern sources:
core/src/feature/ciede.c(closest analog),core/src/feature/ssimulacra2_math.h(deterministic math-helper header pattern). - Source:
req— maintainer task brief specifying PQ-only RC scope, feature namedelta_e_itp, mean pooling,matrix/rangeoptions defaulting to bt2020/limited, double-precision math, no out-of-gamut clamping, and the places=4 ITP-triple oracle.