import type { MediaContext, PlaybackSession, TransportConfig } from "../../types.js"; import { VideoRenderer } from "../fallback/video-renderer.js"; import { AudioOutput } from "../fallback/audio-output.js"; import { startHybridDecoder, type HybridDecoderHandles } from "./decoder.js"; import { makeTimeRanges } from "../../util/time-ranges.js"; /** * Hybrid strategy session. * * Uses libav.js for demuxing + WebCodecs VideoDecoder for hardware-accelerated * video decode + libav.js software decode for audio. Same canvas + Web Audio * output as the fallback strategy. * * Falls back to the pure-WASM fallback strategy if WebCodecs fails (via the * onFatalError callback that the player wires to its escalation mechanism). */ const READY_AUDIO_BUFFER_SECONDS = 0.3; const READY_TIMEOUT_SECONDS = 10; export async function createHybridSession( ctx: MediaContext, target: HTMLVideoElement, transport?: TransportConfig, ): Promise { // Normalize the source so URL inputs go through the libav HTTP block // reader instead of being buffered into memory. const { normalizeSource } = await import("../../util/source.js"); const source = await normalizeSource(ctx.source); const fps = ctx.videoTracks[0]?.fps ?? 30; const audio = new AudioOutput(); const renderer = new VideoRenderer(target, audio, fps); let handles: HybridDecoderHandles; try { handles = await startHybridDecoder({ source, filename: ctx.name ?? "input.bin", context: ctx, renderer, audio, transport, }); } catch (err) { audio.destroy(); renderer.destroy(); throw err; } // Patch