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

11 KiB

status, date, definition
status date definition
draft 2026-05-20 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: 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 section flags this as "deserves a dedicated home" with high reuse — consumers include HEVC variant selection, 5.1 surround selection, 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) (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 (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.

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 (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-selectionconsumer. Uses Tier 1 (select HEVC if supported, fallback to AVC)
    • cross-codec transition probing (mid-stream switching).
  • 5.1-surround-selectionconsumer. 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 (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 switchconsumer 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 behaviorsselectVideoTrack / 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 pathcreateSourceBuffer'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-abrselectQuality 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, 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 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.
  • 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 — consumer; selection + cross-codec switching.
  • 5.1-surround-selection — consumer.
  • drm-support (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 — 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