Files
v10/internal/design/spf/features/capability-probing.md
T

187 lines
11 KiB
Markdown

---
status: draft
date: 2026-05-20
definition: technical
---
# Capability probing
The engine's foundation for determining what the browser can actually
play: codec / container support via `MediaSource.isTypeSupported` and
`canPlayType`, key-system support via `requestMediaKeySystemAccess`,
and `SourceBuffer.changeType()` availability for mid-stream codec
transitions. Filters the candidate set *before* selection, so
unsupported renditions don't survive into the pipeline and fail late.
A **Media-src feature** in the framing from
[clusters.md § Feature classification axes](./clusters.md#feature-classification-axes):
without it, sources with browser-incompatible variants fail late at
`createSourceBuffer` instead of failing gracefully (or falling back to
a compatible variant). Cluster D foundation; the
[clusters.md § Capability probing](./clusters.md#capability-probing)
section flags this as "deserves a dedicated home" with high reuse —
consumers include [HEVC variant selection](./hevc-variant-selection.md), [5.1 surround selection](./5.1-surround-selection.md),
DRM, and the unsupported-case error mapping.
## Status
- **Composition:** not implemented in `createSimpleHlsEngine`. A
single late-failure check exists today: `isCodecSupported` in
`media/dom/mse/mediasource-setup.ts` is called by `createSourceBuffer`
inside `setupVideoBufferActors` / `setupAudioBufferActors` — by which
point selection has already run and an unsupported variant may have
been picked.
- **Definition depth:** technical — scope and constraints articulated;
no implementation. Source material: [SPF Epics Working Doc —
candidate epics #17 (codec / container), #18 (multivariant CODECS),
#19 (key-system)](https://www.notion.so/35f97a7f89d08123a13fecab1ca1cac4)
(cluster D; each sized S; the Epics doc flags #17 + #18 as likely
merging).
- **Foundational** for cluster D — `[hevc-variant-selection]`,
`[5.1-surround-selection]`, `[unsupported-case-error-mapping]`, and
[drm-support](./drm-support.md) (GitHub issue #1411) all consume
probing output.
## Phases of complexity
Scope slices around the capability-probing contract. Tier 1
(spec-compliant filtering) and Tier 2 (customer-driven overrides)
layer onto specific phases per the
[Tier 1 / Tier 2 framing](./clusters.md#tier-1-spec-compliant-baseline-vs-tier-2-custom-behavior).
| Phase | What | Notes |
|---|---|---|
| Codec / container probing primitive | Uniform API wrapping `MediaSource.isTypeSupported` + `canPlayType`. Helpers for "given a `Track`, can we play it?" Builds on today's `isCodecSupported` | The minimum primitive everything else builds on. Today's `isCodecSupported` is the codec half; the wrapper formalizes the surface |
| Multivariant CODECS-attribute filtering | At presentation resolution (post-parse), filter `presentation.selectionSets` to drop renditions whose `CODECS` doesn't decode on this browser. Filtered set is what selection behaviors operate over; unsupported renditions never reach selection | Tier 1 (spec-compliant). Today's late-failure path becomes a defensive fallback rarely exercised |
| Media-playlist / segment-level capability checking | Per-segment CODECS verification + container detection at the media-playlist level. Catches mismatches the multivariant didn't declare | Tier 1. Largely defensive; expected to be rare for well-formed manifests |
| Key-system capability probing | `requestMediaKeySystemAccess` for each candidate key system (Widevine, PlayReady, FairPlay, FairPlay-AirPlay). Returns supported configurations. **DRM-adjacent boundary:** this feature owns Tier 1 probing only; EME setup, license fetch, key delivery live under [drm-support](./drm-support.md) (GitHub issue #1411) | Async — pushes toward a new-behavior filter writer pattern rather than a derived signal |
| Cross-codec transition (`changeType()`) probing | Probe whether `SourceBuffer.changeType()` is available, plus pair-wise support for specific codec transitions (AVC ↔ HEVC, AAC stereo ↔ AC-3 5.1, etc.). Browser support is fragile and pair-specific | Consumers decide whether to attempt mid-stream switches based on this probe; the `changeType()` call itself lives in those consumer features |
| Unsupported-case error surfacing | When no candidate survives filtering, surface a clear error rather than failing late in `createSourceBuffer`. State-error slot or callback — the interface is defined here; consumer-side mapping lives in `[unsupported-case-error-mapping]` | The "fail loudly upstream" path |
| Tier 2: customer probing overrides | Config-driven biases: "force AVC even when HEVC supported," "prefer hardware-backed DRM," "exclude codec X." Layered on top of Tier 1's spec-compliant filtering | Tier 2 (custom behavior). Often consumer-policy-driven |
## What's in scope vs out of scope
**In scope:**
- All phases above
- Browser-API wrappers (`isTypeSupported`, `canPlayType`,
`requestMediaKeySystemAccess`, `changeType()` availability)
- Filter-writer behavior + the filtered-candidate-set slot pattern
- Error-surfacing primitive (used by both this feature and
`[unsupported-case-error-mapping]`)
**Out of scope (separate Media-src candidate features):**
- **[hevc-variant-selection](./hevc-variant-selection.md)** —
*consumer*. Uses Tier 1 (select HEVC if supported, fallback to AVC)
+ cross-codec transition probing (mid-stream switching).
- **[5.1-surround-selection](./5.1-surround-selection.md)** —
*consumer*. Same shape as HEVC, on the audio channel-count axis.
Adds a 5.1-specific runtime-detection phase (downstream-environment-
aware channel preference) with no HEVC analog.
- **[drm-support](./drm-support.md)** (GitHub issue #1411) — EME
setup, license handling. This feature owns the "what key systems
are available?" probe; drm-support uses that answer to set up
keys.
- **Multi-language-audio Tier 2 mid-stream codec switch** —
*consumer* of `changeType()` probing.
- **`[unsupported-case-error-mapping]`** — sister feature; maps the
error-surfacing primitive to consumer-facing codes / messages.
**Out of scope (different architectural layer):**
- Adapter / consumer-side error display
- Consumer-specific error-code mappings (above-engine)
## Likely cross-cutting impact
- **Selection behaviors** — `selectVideoTrack` / `switchVideoQuality`
/ `selectAudioTrack` / `selectTextTrack` pickers read filtered set,
not raw `presentation.selectionSets`. Same shape as the
`userVideoTrackSelection` constraint pattern in `video-abr`.
- **`mse-mms-pipeline` late-failure path** — `createSourceBuffer`'s
throw on unsupported codec becomes a defensive fallback. With
upstream filtering it should rarely fire; the throw stays as a
structural guarantee.
- **`presentation-modeling`** — parser stays format-neutral.
Capability filtering is post-parse, before selection. The
architectural doc's parser-interface contract isn't affected.
- **`video-abr`** — `selectQuality` operates over the filtered set.
No code change in ABR itself; just narrower input.
- **DRM gate** — key-system probing becomes the *first* DRM gate.
Subsequent EME setup, license fetch, key delivery happen under
[drm-support](./drm-support.md), gated on probing's verdict.
Crisp boundary:
probing answers "can we?"; DRM-support answers "set it up."
- **Cross-codec transition consumers** — HEVC, 5.1, multi-language-
audio Tier 2 all need `changeType()` probing. The actual
`changeType()` call lives in their own feature work; this feature
provides the "can we?" answer.
## Open questions
- **Filter-writer pattern.** New behavior vs derived signal? Async
key-system probing pushes toward new-behavior (writes a filter
slot after async resolves). Synchronous codec probing could be a
derived signal. Unified or split?
- **Cache-eager vs lazy probing.** Probe everything upfront (simpler,
worst-case cost) vs probe-on-demand (more efficient for sources
with many renditions). Affects state-slot writer pattern.
- **`changeType()` pair-wise probing API.** Probe all pairs upfront,
probe lazily on switch attempt, or expose a `canChangeType(from,
to)` predicate that callers invoke?
- **Tier 2 customer override surface.** Config-driven (engine-wide)
vs per-source vs both? Per-source is more flexible but harder to
wire.
- **Container-detection scope.** [container-support](./container-support.md)
is documented as standalone (cluster-less; MSE doesn't accept
non-fMP4 containers per spec, so the concern is structurally
different from capability-probing's "what can the browser decode
in fMP4?" framing). Open: should this feature surface container-
format detection as part of multivariant filtering (filter out
MPEG-TS variants when no transmuxer is composed)? That would
resolve the scope intersection cleanly without building the
transmuxer.
## Related features
- **mse-mms-pipeline** — owns `isCodecSupported` + the late-failure
path. This feature builds on those and moves the check upstream.
- **presentation-modeling** *(architectural)* — data shape this
feature filters; parser stays format-neutral.
- **video-abr** — quality selection narrowed to filtered candidates.
- **audio-playback** / **subtitles** — per-type selection over
filtered candidates.
- **multi-language-audio** *(coarse)* — Tier 2 mid-stream codec
switch consumes `changeType()` probing.
- **[hevc-variant-selection](./hevc-variant-selection.md)** —
consumer; selection + cross-codec switching.
- **[5.1-surround-selection](./5.1-surround-selection.md)** —
consumer.
- **[drm-support](./drm-support.md)** (GitHub issue #1411) — owns EME +
license; consumes key-system probing.
- **`[unsupported-case-error-mapping]`** *(candidate)* — sister;
consumer-facing error mapping on top of this feature's error
primitive.
- **[container-support](./container-support.md)** — standalone
feature (cluster-less); resolved per the doc's framing that MSE
doesn't accept non-fMP4 containers per spec, making the concern
fundamentally different from capability-probing's framing.
Container-detection-without-transmuxer remains a possible cross-
feature integration point (filter MPEG-TS variants when no
transmuxer is composed).
## See also
- [clusters.md § Capability probing](./clusters.md#capability-probing)
- [clusters.md § Feature classification axes](./clusters.md#feature-classification-axes)
— Constraint + filter pattern, Composition vs Policy vs middle
pattern (middle pattern), Tier 1 / Tier 2 framing
- [mse-mms-pipeline.md](./mse-mms-pipeline.md) — `isCodecSupported`
+ the late-failure `createSourceBuffer` throw
- [presentation-modeling.md](../presentation-modeling.md) — data
shape this feature filters
- [SPF Epics Working Doc](https://www.notion.so/35f97a7f89d08123a13fecab1ca1cac4)
— epics #17 (codec / container), #18 (multivariant CODECS),
#19 (key-system), #20 (unsupported-case error mapping)
- [Permutations Matrix — Upcoming Features + Unsupported Case Handling](https://www.notion.so/32c97a7f89d08191b84dd30f06685490)
— source material for the consumer features (HEVC, 5.1, DRM
security levels) and error-handling scope