Skip to main content

WAI Extension: Platform Decode Capabilities

Mirrored from the canonical text at commit 260cbd09 ().

Status: Draft. Maps two web platform interfaces, Media Capabilities decodingInfo() and WebCodecs isConfigSupported() with its hardware-acceleration preference, onto the capability report of browser-sink §3: what a sink asks the platform about an entry, read from the entry’s payload (§2), and how the answers enter the report (§3). The answers are hints. They order the alternatives a page can decode, inside browser-sink’s routing, by SPEC §4’s energy order (browser-sink §4.7); they never change a route, are never an energy figure and are never evidence of hardware. No manifest member and no wire format. Keywords MUST, MUST NOT, SHOULD, MAY are RFC 2119/8174.

1. Scope

A sink running in a web platform can decode a standard video codec through the platform’s own decoders, which may be fixed-function hardware, or through a decoder of its own: WebAssembly, or a learned reconstruction such as WAI’s integer codecs. The platform says, for a configuration, whether it can decode it, whether it can do so without dropping frames, and whether it judges the decode power-efficient (Media Capabilities §2.2). A learned reconstruction runs on the sink’s CPU, GPU or neural engine, and what it draws there is known only where it has been measured. This extension says how a WAI sink asks the platform about an entry, and how it enters what the platform says in browser-sink’s capability report, where the routing (browser-sink §4) decides what the page can decode and the energy order (SPEC §4, Energy order; browser-sink §4.7) orders what it can.

It reads these documents:

ISO/IEC 14496-15 was not read. The HEVC codec string §2 writes follows the form the HEVC registration describes (four dot-separated fields of Annex E.3 and the constraint bytes after them), checked against an open-source parser of that form (Chromium’s ParseHEVCCodecId) and against a platform that decodes with it (§5).

2. The query

For an entry whose capability the table maps, the sink forms the query from the entry’s payload. It MUST NOT form it from anything the envelope declares apart from the payload: the codec string a payload’s encoder declared can differ from the stream (§5 records one that did).

capabilitycodec stringsizeframe ratebit rate
wai.video.av1, wai.video.av1.losslessfrom the first temporal unit’s sequence header OBU: av01., the profile, the level (two digits) and the tier (M or H), the bit depth (two digits); then the monochrome flag, the chroma subsampling (three digits), the colour primaries, transfer characteristics and matrix coefficients (two digits each, 01 each where the sequence header carries no colour description), and the full-range flag; the part after the bit depth omitted where it is exactly .0.110.01.01.01.0 (AV1-ISOBMFF §5)w × h of SPEC §5’s AV1 framingfps_num / fps_den of the framingthe payload’s bits × the frame rate ÷ n, rounded up
wai.video.hevcfrom the first SPS NAL unit (H.265 §7.3.2.2, §7.3.3): hev1.; the profile space as nothing, A, B or C, then general_profile_idc in decimal; the 32 general_profile_compatibility_flags as one hexadecimal value with flag j at bit j; L or H for general_tier_flag, then general_level_idc in decimal; then the six bytes from general_progressive_source_flag on, each in hexadecimal, trailing zero bytes omitted. hev1 because an Annex B stream carries its parameter sets in bandpic_width_in_luma_samples × pic_height_in_luma_samples, less the conformance window; the coded size before itnone in the payload: the rate the sink will present at, where it has onethe payload’s bits × the frame rate ÷ the pictures the stream holds, rounded up

A capability the table does not map is not queried: the sink decodes it, or does not, as it otherwise would, and the order of §4 places it by its class alone.

The sink asks:

WebCodecs gives no smoothness or power answer, and Media Capabilities has no WebCodecs decoding type. A sink that decodes through WebCodecs asks isConfigSupported() first, and asks decodingInfo() of the media-source query of the same configuration only once isConfigSupported() answers supported, and only for a codec string browser-sink §4.2’s registry gate passes: Media Capabilities is a further question about a decoder already found (http-delivery §12.2). It reads smooth and powerEfficient from that answer as hints and nothing more (§3).

3. The answers

A page enters what the platform said in browser-sink §3’s capability report, one answer per codec string, {supported, smooth, power_efficient, probe}, and in no other shape (platform_decode::report_answer):

The hardware-acceleration preference. prefer-hardware and prefer-software are hints a user agent may ignore for any reason (WebCodecs §7.9). An isConfigSupported() answer of supported: true with prefer-hardware says the platform accepts that configuration with that preference; it is not evidence that the decode runs on hardware, and a sink MUST NOT report it as such.

Privacy. The answers can be used to fingerprint the sink (Media Capabilities §3.2). A sink SHOULD NOT send them, or the order they give, to any party; the order is computed where the answers are. A platform that fakes its capabilities to resist fingerprinting (§3.2 recommends a fixed set rather than always yes or always no) gives answers the order uses as given: the result is a choice that platform made, and the decode still conforms.

4. The order the answers feed

This extension defines no order of its own, and no second meaning of “the sink advertises cap”. What a page advertises for an object is its route (browser-sink §4.3, SPEC §4). Among alternatives the page can route, SPEC §4’s energy order applies, as browser-sink §4.7 writes it: first for classical decode routed ua that the platform answers supported, smooth and power-efficient, then smooth, then classical (any other routed classical decode, and a learned one with a qualifying sink-metered figure in browser-sink §6’s energy entry), then learned-without-budget. A WAI1 envelope’s capability and fallback are two such alternatives. The order reads no figure’s value (browser-sink §6).

5. Conformance

The reference implementation is wai::platform_decode (wai/wai-rs/src/platform_decode.rs): query forms §2’s query, and report_answer §3’s answer. It calls no platform: the answers are inputs. The vectors are in wai/platform-decode-conformance/: queries.json, two floor objects of the packaging corpus, whose codec string is the one the packager wrote into its HLS master, and an HEVC SPS the platform’s encoder wrote through WebCodecs, configured with prefer-hardware. The order’s vectors are the choices of live-conformance/browser/.

An implementation conforms when it gives every query’s members. The reference’s tests (platform_decode::tests) also hold the AV1 codec string to the AV1-ISOBMFF binding’s own examples, derive every floor of the packaging corpus to the codec string and size the packager wrote into the pack’s HLS master, read constructed SPSs with sub-layers and with emulation-prevention bytes, and hold report_answer to §3.

wai-web’s platform_decode bundle binds the same code for a page (platformQuery, platformAnswer, and platformChoose, browser-sink §4.7’s choice), and wai-web/demo/platform_decode.html (verify_platform_decode.mjs) runs it against a browser’s platform: every AV1 floor object of the packaging corpus, queried and decoded through WebCodecs with the configuration its payload’s query gives; an HEVC stream the platform’s encoder writes, queried from that stream and decoded back; and the choice between a learned alternative and an AV1 floor object, from the report the page built from those answers. Every query the page asks is read from a payload.

Measured 2026-10-22 with that page on an arm64 desktop (macOS 27.0.1), in headless Chromium 148 and a Chromium-based browser at 155, with the same results in both, before the page’s order moved into browser-sink’s routing:

The choice step of the page was rewritten with the order and has not been run in a browser in this revision; a 1920×1080 answer the earlier page reported was for a configuration written by hand, not read from a payload, and is not restated. Not measured: a platform without hardware AV1 or HEVC decode, a platform that fakes its answers, and any engine but Chromium’s.

6. Security and privacy considerations

The answers are fingerprinting surface (§3, Privacy). The order reads them where they are produced and sends nothing. The query reads only the payload’s headers; a malformed payload gives no query, and the entry is decoded, or not, as it would be without this extension. An encoder cannot raise an entry’s rank by what it declares: the codec string is read from the payload, the class from the registry, the route from browser-sink’s routing, and a learned entry ranks with classical decode only on a sink-metered figure the sink holds, never on one an envelope carries.