Files
v10/dist/dev/media/dom/capabilities.js
T

70 lines
3.6 KiB
JavaScript

import { NON_FMP4_CONTAINER_MIMES } from "../hls/parse-media-playlist.js";
import { buildMimeCodec, isCodecSupported } from "./mse/mediasource-setup.js";
//#region src/media/dom/capabilities.ts
/**
* Capability probing — the engine's foundation for asking the browser what it
* can actually decode before committing a rendition to the pipeline.
*
* Today this is the synchronous codec half: `canPlayTrack` answers "can this
* environment play this track?" by building the track's MIME codec string and
* passing it to `MediaSource.isTypeSupported` (via `isCodecSupported`). It's the
* DOM implementation of the DOM-free `CanPlayTrack` predicate the
* track-switching hard-constraint pre-pass consumes — injected through engine
* config so the (DOM-free) behavior never imports a DOM API directly.
*
* Results are memoized by built MIME string: codec support is a pure function
* of (codec, environment) and never changes after load, so probing is lazy
* (per candidate, at constraint-apply time) but each unique MIME is asked once.
*
* Future cluster-D phases (async `requestMediaKeySystemAccess` key-system
* probing, `SourceBuffer.changeType()` availability) extend this surface; the
* async ones land as a state-slot writer behavior rather than a config
* predicate, since their verdict resolves asynchronously.
*/
const codecSupportCache = /* @__PURE__ */ new Map();
/**
* Whether the environment can decode `track`, by codec. Builds the track's
* MIME codec string and checks `MediaSource.isTypeSupported`, memoized by MIME.
* A track without enough to probe — no `mimeType`, or no declared `codecs`
* (CODECS is optional per the HLS spec) — is unprobeable and passes through as
* playable (`true`) rather than being dropped; the late `createSourceBuffer`
* check stays as the backstop for those.
*
* Detected non-fMP4 containers (`video/mp2t`, `audio/aac`) are asserted
* unsupported regardless of the probe, so they're pruned before selection
* (the type makes no pick) instead of failing/stalling deep in the pipeline.
* Two different reasons, neither UA-based:
*
* - **MPEG-TS** can't be played at all here: `isTypeSupported('video/mp2t…')` is
* a genuine false positive on Chromium (reports `true` but appends produce no
* buffered range), and this engine has no TS transmux pipeline.
* - **Raw ADTS AAC** is a *temporary* limitation. The browser genuinely
* supports it (Chrome/Safari decode `audio/aac`; Firefox doesn't), so it could
* be made playable — but our segment actors / loading behaviors / append
* pipeline assume every rendition has an `EXT-X-MAP` init segment (e.g. an
* `append-init` task with an empty URL, fMP4-shaped append handling). Until
* that init-segment assumption is removed, ADTS would fetch but never buffer
* (a silent stall), so we assert it unplayable for now. FOLLOW-UP: drop the
* init-required assumption in the pipeline and switch this to a bare-MIME
* probe (`buildMimeCodec` would project `audio/aac` with no codecs) so it
* plays where the browser supports it.
*
* Override via the engine's `canPlayTrack` config when those pipelines land.
*/
const canPlayTrack = (track) => {
if (track.mimeType && NON_FMP4_CONTAINER_MIMES.has(track.mimeType)) return false;
if (!track.mimeType || !track.codecs?.length) return true;
const mimeCodec = buildMimeCodec({
mimeType: track.mimeType,
codecs: track.codecs
});
const cached = codecSupportCache.get(mimeCodec);
if (cached !== void 0) return cached;
const supported = isCodecSupported(mimeCodec);
codecSupportCache.set(mimeCodec, supported);
return supported;
};
//#endregion
export { canPlayTrack };
//# sourceMappingURL=capabilities.js.map