open-standards/wai/extensions/derived-tracks.md
Transaction Science 258fd918ec deriving edge: second implementation, CI step, registry, SPEC §5 and CHANGELOG
edge-conformance/edge_verify.py verifies the corpus from the extension's
text alone: it reads receipts and writes stills itself, re-executes every
replicate hop, requires every mutated copy of the corpus to fail and the
corpus to catch it with each of its own checks dropped. Two controls are
added so that every one of its checks is caught (a JPEG output naming no
encoder, a grid stated over more inputs than its cells).

The registry lists wai.edge.derivation and the document kind
wai-derivation; jwp-receipts §4.2 and §7.5 register what an edge may do
and its authority edge/derive; derived-tracks and energy-measurement say
where the receipt and the group receipts now come from.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-21 04:38:26 -04:00

328 lines
23 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# WAI Extension: Derived Tracks
> Status: Draft. Registers the derivation operations of ISO/IEC 23001-16:2021
> as `wai.derive.*` capability strings, each with a **per-operation determinism
> tier**, and states how a tier composes over a derived sample. No wire format,
> and no compositing. The geometric conditions listed per operation are read
> from the operations' titles: clause 8 of ISO/IEC 23001-16, which defines each
> operation, was not read. Reference impl: `wai-rs` `codecs::derivation`.
> Keywords **MUST**, **MUST NOT**, **SHOULD**, **MAY** are RFC 2119/8174.
## 1. Prior art, stated plainly
A track that carries a process the receiver evaluates, rather than the processed
result, is not new. **ISO/IEC 23001-16:2021**, *Derived visual tracks in the ISO
base media file format* (1st edition, 2021-11), ratified it. A derived visual
track (sample entry `dtrk`) carries derived samples, each active for a duration
of the track's composition timeline. Each derived sample is an ordered list of
derivation operations, each applying a derivation transformation, with its
parameters, to an ordered list of inputs. An input is either a **visual input**
(an image item, an interval of an input track or track group possibly spanning
several samples, the visual output of a preceding operation, or a default fill
picture) or a **parameter input** (a metadata item, or an interval of a metadata
track possibly spanning several samples). A parameter takes the value the derived
sample gives it, else the value in the sample entry, else the default its
transformation's clause defines. A visual output is one frame or a sequence of
frames, and any transformation may have internal time structure (the standard's
example is a cross-fade), so the picture may change during the sample's duration.
Operations chain, and a derived track can be an input to another. The first
edition defines a base set of ten transformations, each identified by a
four-character code, with `'uuid'` reserved for vendor transformations identified
by UUID.
The parts of that specification read for this extension (clauses 1–4, 5.1 and
5.2, and the table of contents, from the published sample, which ends at 5.2) do
not say whether an operation's output reproduces byte for byte across conforming
readers. The rest was not read: clause 5.3 (the semantics of the derivation
boxes), clauses 6 and 7 (the sample entry, the configuration record and the
sample format), clause 8, which gives each operation's definition, syntax and
semantics, and so any blend or resampling formula, and Annex A. This extension
states, per operation, when a
claim over its output may hold, in the vocabulary of
[determinism-tiers](determinism-tiers.md), so a receipt or binding over a derived
sample can say which tier it actually holds. Every tier rests on conditions that
the sink which executed an instance checks on that instance, in space and in
time. Clause 8 decides what an instance does, and so which conditions it can
meet. What the registry takes from outside clause 8 is each operation's purpose,
read from its title, which decides the geometric conditions listed for it (§2,
*Basis of the tiers*). The tiers are not uniform. Dissolve and Scaling compute
new sample values by their nature. The others are exact only for instances that
copy samples without converting them, and whose output does not change over the
span a claim covers.
**Scope.** WAI does not composite. Presentation stays with the sink, as in
[linear-film](linear-film.md) and [interactive-worlds](interactive-worlds.md).
Registering grid and overlay composition states what a reproducibility claim over
their output would need; it does not make WAI a renderer. Registering the
operations aligns WAI's vocabulary with the standard; it says nothing about which
players evaluate derived visual tracks.
## 2. Registered operations
An executed instance of an operation is **exact** when every output sample is a
copy of an input sample, or of a constant the claim names, placed by integer
geometry, with no arithmetic on sample values, no change of sample
representation, and no change over the span the claim covers. Inputs at
`decode-equivalence` give an exact instance's output at `decode-equivalence`. A
per-operation tier is one of:
- **exact when (conditions)**: an executed instance is exact when it meets the
three universal conditions below and every condition the table lists for its
operation, and untiered otherwise. The conditions are properties of the
executed instance, checked by the sink that executed it. **No operation is
exact unconditionally**, Identity included.
- **untiered**: the operation computes new sample values, by blending or
resampling, and WAI pins no arithmetic for it. The output carries no tier,
whatever its inputs held, until an arithmetic is pinned and an instance is
shown to follow it. Dependence on time is not what makes an operation
untiered: every operation needs time-invariant.
The three **universal conditions**, required of every tiered operation:
- **same-representation**: every visual input, and every constant the instance
writes (a fill colour, the default fill picture), is already in the output's
sample representation: the same bit depth, chroma format and chroma siting,
colour primaries, transfer characteristics, matrix coefficients, range and
component set. No sample value is converted. Clause 4 requires the visual
inputs of a derived sample to share pixel aspect ratio and bit depth with each
other; the clauses read say nothing about the other properties, or about the
output's representation relative to its inputs. So an 8-bit input composed into
a 10-bit output, a BT.709 input composed into a BT.2020 output, or an Identity
whose output representation differs from its input's holds no tier.
- **copies-only**: every output sample value is, bit for bit, the value of an
input sample or of a constant whose value the claim names. The instance
computed no sample value.
- **time-invariant**: over the span the claim covers, every visual input the
instance reads is one frame and every parameter it uses has one value. The
instance also has no time structure of its own, such as a transition or a
parameter interpolated over time. So its output over the span is one frame,
fixed by those frames and values. The span is either the derived sample's
whole duration or one output frame at a composition instant the claim names
(§3 rule 3). A parameter counts whatever its source: the derived sample, the
sample entry, the default of the operation's clause, or a parameter input.
Clause 4 lets one derivation duration span several samples of an input track,
and lets any transformation have internal time structure. A visual or
parameter input may be an interval of a track spanning several samples, and a
visual output may be a sequence of frames. So two instances hold no tier for a
claim over the whole duration: an ROI selection whose region is driven by an
interval of a metadata track whose value changes within the sample, and an
Identity over an input interval holding several samples. Either can hold one
for a claim over one output frame, at an instant at which nothing it reads
changes, if it has no time structure of its own.
Because every tiered operation requires all three, an instance is untiered, not
over-claimed, if it uses any parameter that clause 8 allows to convert or compute
sample values, or to vary its output over time. This holds as long as the
executing sink lists only the conditions it actually checked.
| capability | 23001-16 clause | operation | tier | conditions beyond the universal three (read from the operation's title; clause 8 was not read), or why untiered |
|---|---|---|---|---|
| `wai.derive.identity` | 8.2 | Identity | exact when | none. It copies its input; uncovered output samples come from the default fill picture, a constant the claim must name (§3 rule 5). Whether clause 8 lets Identity emit a representation other than its input's was not read, so same-representation is checked, not assumed |
| `wai.derive.srgb_fill` | 8.3 | sRGB Fill | exact when | none. The colour is stated in sRGB; writing it into any other representation is a conversion, which same-representation excludes. As its title is read, it reads no visual input, and it is the only operation registered as reading none |
| `wai.derive.dissolve` | 8.4 | Dissolve | untiered | a transition that mixes two inputs, so its output values are computed, not copied. A transition is also time structure of its own, which time-invariant excludes for every operation (clause 4's example of internal time structure is a cross-fade). Untiered until a blend arithmetic, and how its weights depend on the instant, are pinned; clause 8.4, which may fix them, was not read |
| `wai.derive.crop` | 8.5 | Crop | exact when | the kept region lies on the sample grid of every component (no component is resampled) |
| `wai.derive.rotation` | 8.6 | Rotation | exact when | the angle is a multiple of 90°, and every component is sampled at the same resolution, so the rotation permutes samples |
| `wai.derive.mirror` | 8.7 | Mirror | exact when | the reflection maps every component's sample grid, including its siting, onto itself (always so without chroma subsampling) |
| `wai.derive.scaling` | 8.8 | Scaling | untiered | resamples, so its output values are computed, not copied. Untiered until an interpolation filter and its rounding are pinned; clause 8.8, which may fix them, was not read |
| `wai.derive.roi_selection` | 8.9 | Region of interest (ROI) selection | exact when | the region lies on the sample grid of every component, and is emitted at its own size |
| `wai.derive.grid_composition` | 8.10 | Grid composition | exact when | every input is placed at its own size, at offsets on every component's sample grid |
| `wai.derive.overlay_composition` | 8.11 | Overlay composition | exact when | every input is placed at its own size, at offsets on every component's sample grid, and opaquely (no alpha, opacity or blending) |
- **Identification.** Each capability string stands for the transformation its
clause defines, including that clause's four-character code. The registry does
not yet record the codes: clause 8 of the published text was not available when
this was written. A sink maps each capability to the code its clause defines,
and MUST NOT map one by a code taken from any other source. Codes from earlier
drafts circulate in secondary sources.
- **Basis of the tiers.** Tiers are assigned from what each operation does to
sample values, in space and in time, not from clause 8, which was not read.
Each condition is a property of an executed instance, not of parameter syntax.
The three universal conditions exclude any conversion or computation of sample
values, and any change over the span a claim covers. What is taken from outside
clause 8 is each operation's purpose, read from its title (a crop selects, a
rotation rotates), which decides the geometric conditions listed for it, and
whether it reads a visual input at all (only sRGB Fill is registered as reading
none). Reading clause 8 may show one of those lists to be incomplete. It may
also make some conditions unnecessary (for example, if Rotation admits only
quarter turns, or if the output representation is always the inputs'). Clause 8
may also fix a blend or resampling arithmetic bit-exactly; that would be the
start of a pin for Dissolve or Scaling, not a tier in itself. Clause 4, which
was read, already shows where a list may fall short: wherever an input's size
differs from the output's, the input is cropped or filled implicitly, for every
operation unless the operation's clause overrides that. The fill is covered by
§3 rule 5. The clauses read do not say where such an input is placed, and no
list, Identity's included, carries a condition on that placement.
- **Correction.** An earlier revision said that no tier here rested on anything
clause 8 might fix. The time dimension did. Only Dissolve was untiered for
depending on time, as if clause 4's cross-fade were particular to it, but
clause 4 states generally that a derivation transformation may have internal
time structure. Time-invariant is now a universal condition.
- **Not payload capabilities.** An operation names no payload format; it acts on
samples another capability decoded. SPEC §4 assigns every payload exactly one
capability, so these strings are not in `codecs::known_capabilities` and a
manifest cannot name one as its payload's capability. A sink advertises the
operations it evaluates the way it advertises codecs.
- **Licence.** The Introduction of ISO/IEC 23001-16:2021 records a patent claimed
to be required for compliance, whose holder has given a
reasonable-and-non-discriminatory licensing assurance. The registry classifies
the operations as patent-pool, conservatively
(`codecs::derivation::derivation_license`).
## 3. Composing a tier over a derived sample
1. **Weakest step.** A derived sample holds `decode-equivalence` only if every
visual input holds `decode-equivalence` and every executed operation instance
is exact: it meets the three universal conditions and every condition listed
for its operation. Otherwise it holds no tier, and a receipt over it MUST NOT
carry a reproducible derived-sample hash.
2. **`entropy-consistency` does not pass through.** Derivation operations act on
reconstructed samples, which that tier does not fix. A derived sample over an
input at `entropy-consistency` holds no tier.
3. **The claim is about what was executed, with what, and when.** ISO/IEC
23001-16 lets a reader treat an unsupported non-essential operation as a null
operation, so two conforming readers can emit different samples from one
derived sample. A parameter can come from a metadata track, and the output
can change within the sample's duration. A tier claim or receipt over a
derived sample MUST name:
- the operations executed, in order;
- for each instance, the parameter values it applied, whatever their source
(the derived sample, the sample entry, the default of the operation's
clause, or a parameter input), with any region, offset or size expressed in
samples;
- the span it covers. For a claim over the whole duration, that is the derived
sample's composition time and duration on the derived track's timeline, in
its timescale. Otherwise it is the composition instant of each output frame
the claim covers;
- its inputs, visual and parameter, by content hash. For an interval of a
track, the hash covers the samples the instance read.
Two sinks' derived-sample hashes are comparable only when all four are equal.
A sink MUST NOT present a hash computed with an operation skipped as the hash
of the sample with that operation, and MUST NOT present the hash of one output
frame as the hash of a derived sample whose output changes over its duration.
4. **Transforms applied before derivation count.** ISO/IEC 23001-16 applies the
transformative properties of inputs (clean aperture, track matrix, and the
like) before the derivation operation. For a tier claim each counts as a step,
tiered as the registered operation it performs. A unity matrix is identity; a
quarter-turn or reflection matrix is rotation or mirror; a clean aperture is a
crop. Any other matrix is untiered, whether or not it resamples (a scale, a
shear or a sub-sample translation does): the registry pins no arithmetic for
it.
5. **The default fill picture is an input.** Where output samples come from the
configuration record's default fill (black, grey or white), whatever the
operation, the claim MUST name the fill's sample values in the output
representation. A fill whose values the claim does not name is an input with
no tier, and an instance that writes it does not meet copies-only. An input
that neither the derived sample nor the sample entry lists is the default fill
picture (clause 5.1). So an operation reads the fill for every visual input it
reads that neither lists, and a claim over it names the fill as an input.
Where an instance sits in the executed list does not say what it read: clause
4 lets an operation that is not first read the output of any previous
operation, only new inputs, or both. A claim therefore names, for each
instance, the visual inputs it read: an input, or the output of an operation
executed before it. An instance of an operation that reads a visual input and
names none holds no tier, wherever it sits in the list.
6. **Unregistered operations cannot be tiered.** A `'uuid'` vendor operation, or
any transformation this registry does not name, makes the derived sample
untiered. The reference implementation returns an error rather than guess.
7. **Relation to [determinism-tiers](determinism-tiers.md) §2.** That section's
rule is that a determinism claim covers what the sink emits. A derived sample
is an emitted medium, and this section says when a claim over it holds. It
does not relax the rule for the inputs: a hash over a decoded input is not a
hash over the derived sample.
## 4. Receipt
A receipt over a derived sample SHOULD carry:
- the executed operation list, as capability strings in order, with the
conditions each instance met, the universal ones included, the visual inputs
each instance read (§3 rule 5), and the parameter values each instance applied
(§3 rule 3);
- the span the claim covers: the derived sample's composition time and
duration, or the composition instant of each output frame covered;
- the content hashes of the inputs, visual and parameter;
- the resulting tier;
- only when that tier is `decode-equivalence`, the hash of each output frame the
claim covers. A claim over the whole duration covers one frame.
The energy of evaluating the graph is measured and attributed as for any other
work ([energy-measurement](energy-measurement.md)). The tier and the energy are
separate claims, and neither implies the other. This extension defines the
content of such a receipt, not a field layout; [deriving-edge](deriving-edge.md)
§5 gives one, for the derivations an edge makes and publishes.
## 5. Reference implementation
`wai-rs`, module `codecs::derivation`, with no feature gate:
- `derivation_operations()`, the ten registered operations in clause order
(`DerivationOp { capability, name, clause, fourcc, tier, basis,
reads_visual_input }`, with `fourcc` `None` throughout and
`reads_visual_input` false only for sRGB Fill);
- `derivation_op(cap)` and `is_derivation_operation(cap)`;
- `Condition` (`SameRepresentation`, `CopiesOnly`, `TimeInvariant` — together
`UNIVERSAL_CONDITIONS` — and the per-operation conditions), with
`Condition::statement()`;
- `OperationTier { ExactWhen(&[Condition]), Untiered }`,
`DerivationOp::exact_conditions()` (the universal conditions followed by the
operation's own) and `DeterminismTier { EntropyConsistency, DecodeEquivalence }`
(the registry's `codecs::DeterminismTier`, re-exported);
- `derived_sample_tier(inputs, executed) -> Result<Option<DeterminismTier>,
DerivedSampleError>`, which implements rules 1, 2, 5 and 6 of §3 over an
executed list of `ExecutedOp { capability, conditions_met, reads }`. The
conditions met are listed one by one, so a sink that checked only geometry
cannot meet same-representation or time-invariant by omission. `inputs` lists
the tier of every visual input read other than a preceding operation's output,
the default fill picture included. `reads` names what each instance read, as
`VisualInput::Listed(k)` (entry `k` of `inputs`) or `VisualInput::Preceding(j)`
(the output of executed operation `j`, which comes before it). An instance of
an operation that reads a visual input and names nothing gives no tier,
wherever it sits in the list. When at least one operation executed, a call that
contradicts itself is an error: a reference to an input that is not listed, to
an operation that does not precede the reader, or a listed input that no
instance names. An empty executed list gives no tier before any of these
checks, whatever `inputs` holds. What cannot be
detected is a `reads` that leaves out an input its instance read, unless that
input is listed and no instance names it. The result is as sound as the sink's
report of what each instance read, as it is as sound as its report of the
conditions it checked. An earlier revision
refused a tier on an empty `inputs` only when the first executed operation
read a visual input, so an operation after an sRGB Fill could still read an
input nobody listed and be reported exact;
- `derivation_license()`.
`codecs::derivation` evaluates no derivation operation and emits no receipt, so
rules 3 and 4 of §3, and the receipt content of §4, are not implemented there.
The deriving edge's module (`derive_edge`, feature `derive_edge`;
[deriving-edge](deriving-edge.md)) evaluates the operations that extension
registers, over 8-bit RGB stills read at one frame each, reads which of them are
exact from `derived_sample_tier`, and signs a record carrying §4's content.
`ExecutedOp` carries only what the tier depends on (the conditions met and the
inputs read), not the parameter values, span or input hashes a claim binds. The
`wai` command-line tool does not yet list these operations.
## 6. Sources
- ISO/IEC 23001-16:2021, *Information technology — MPEG systems technologies —
Part 16: Derived visual tracks in the ISO base media file format*. The published
sample (clauses 1–4, 5.1 and 5.2, and the table of contents; it ends at 5.2) is
the source for the operation
names and clause numbers, 4CC identification and the `'uuid'` escape, the
essential and non-essential rule, the default fill picture, pre-derivation
transforms, the rule that visual inputs share pixel aspect ratio and bit depth,
the kinds of input and output (definitions 3.5–3.8: parameter inputs, and
visual and parameter inputs that are intervals of a track spanning several
samples, and visual outputs that are sequences of frames), the statement that
any derivation transformation may have internal time structure (clause 4, with
a cross-fade as its example), the order in which a parameter or an input takes
its value, an unlisted input being the default fill picture (clause 5.1), the
implicit crop and fill of an input whose size differs from the output's
(clause 4), and the patent statement.
The parts read say nothing about bit-exactness either way. What the parts not
read say about it is unknown: clause 5.3 (the semantics of the derivation
boxes), clauses 6 and 7 (the sample entry, the configuration record and the
sample format), clause 8 (each operation's definition, syntax and semantics,
§8.2–§8.11) and Annex A.
- [research/2030-transport-landscape.md](../research/2030-transport-landscape.md)
§3.1 and §8 item 12.