Fastiplayer separates playback policy, media transport, decoding, frame lifetime, rendering, and the desktop shell. The application is the composition root; the playback core consumes contracts rather than concrete GPU or decoder implementations. This document describes the current implementation, not the 1.0 roadmap.
For supported media and measured outcomes, use the compatibility matrix and N15 acceptance. More detailed engineering documents are indexed in docs/README.md; most are in Russian.
| Responsibility | State owner / implementation | Boundary |
|---|---|---|
| Desktop UI and composition | app-egui, egui/winit | User intents, source preparation, concrete backend/renderer selection, window lifecycle |
| Settings schema and transactions | config, settings-core, fastiplayer-settings | Validated descriptors, typed application routes, persistence and rollback |
| Queue and durable identity | playlist-core, playlist-state, playlist-io/discovery | Queue edits, import/export, restore, source identity |
| Byte sources and transport | source-core, web-media-http/ftp, media-prefetch | Bounded reads, seek/cancellation, transport accounting |
| Web discovery and source lifecycle | web-media-core, protocol-specific web-media crates | Provider-neutral catalogs, semantic selection, stable-root reopen/recovery |
| Source opening without UI | media-source-open | Local file and direct HTTP/FTP open, web demux composition, VOD endpoint recovery, extractor catalog projection, shared web-media domain (PreparedMedia composition, stream model with component variants, declared catalog), yt-dlp candidate open intent, component variant finalization, catalog capability probe, HLS/DASH protocol openers and endpoint refresh ports, yt-dlp/extractor open orchestration (web_media_open: candidate → transport → demux composition, content probe and bounded fallback, HDS/Smooth candidate preparation, secret-safe extractor source state), native startup preparation for HLS/DASH/HDS/Smooth (native_startup: manifest fetch, admission, demux composition, typed single extractor-fallback trigger), native source identity/reopen intent/state and the extractor-fallback owner (native_web_source), SafeMediaLabel; background startup jobs (thread, wake mailbox, join) and their StartupMediaController glue stay in app-egui; no egui/winit/wgpu/render or app-egui dependency |
| Container and stream discovery | demux-api, symphonia-demux, mpeg-ts-demux, flv-demux, ac3-elementary-demux | Encoded packets, timing, track metadata and decode-start evidence |
| Playback scheduling and resource ownership | player-core | Session/worker commands and receipts; pipeline-owned decoder, audio and render-resource lifetimes |
| Video backend contracts | video-core, video-backend-api | Capability probing, decode input/output, completion and release |
| Concrete video decode | video-vaapi, video-ffmpeg | VA-API hardware or FFmpeg software implementation behind neutral contracts |
| Frame format and presentation leases | video-frame-contract, video-present-core | Exact layout/bit depth/transfer path and retained-frame lifetime |
| Audio | audio, audio-core, ac3-decoder, audio-timestretch, audio-signalsmith | Decode (incl. own clean-room AC-3/E-AC-3 decoder used only by audio), processing, output and playback clock |
| GPU video rendering | render-core, render-wgpu-video | Materialize frames, GPU color conversion/tone mapping, viewport and render diagnostics |
| Device, surface and presentation | render-wgpu-shell | WGPU device/surface, video + egui composition, submit and present |
The workspace manifest records the actual dependency graph. The eight patched upstream crates are outside the first-party workspace and have separate manifests, locks, licenses, and validation; see the patch inventory.
The application prepares a source through local or web owners, discovers tracks, selects a compatible video plan, and installs the result through the playback boundary. Preparation is not proof of playback: successful consumer tests continue through decode to a submitted/read-back frame or nonzero PCM and an advancing audio clock.
Protocol owners retain their own network, manifest, refresh, and seek invariants. The neutral web catalog exposes source selection intent without leaking extractor-specific implementation types into queue or settings consumers. Supported direct sources take native transport paths; page resolution can use the system yt-dlp adapter.
Installation and restore have distinct outcomes. The strong Installed barrier determines when prepared resources become active; subsequent position/track/intent restoration must still complete or report a partial failure. Generation and media-instance identities prevent stale work from replacing a newer source. Old owners and retained frames must remain valid until their consumers release them.
PlaybackPipeline owns playback resources behind intent methods; session/tick code must not reach into its queues or decoder fields. Backpressure, absent resources, fatal errors, and successful no-ops remain distinct where callers need them. The pipeline modules separate video decode, audio, media slots, render resources, and retired decoders.
A selected video path must satisfy both the stream requirement and the decoder/renderer capability intersection. The frame contract describes layout, bit depth, chroma subsampling, and transfer path. A decoder advertising a codec is insufficient if the renderer cannot consume its exact output.
- Hardware path: video-vaapi decodes to supported VA surfaces; compatible DMA-BUF storage is imported by render-wgpu-video. Zero-copy here means avoiding a CPU pixel copy on this compatible transfer path, not eliminating all synchronization or driver work.
- Software path: video-ffmpeg produces supported host-planar YUV frames, uploaded and rendered through WGPU. Software decoding does not remove the GPU requirement.
- Shared lifetime: presentation retains explicit frame leases. Decoder resources cannot be recycled until the relevant retained consumers and GPU completion/release path permit it. Renderer recreation must respect outstanding resources and renderer generations.
player-core does not depend on concrete WGPU/VA-API/FFmpeg implementations. render-wgpu-video does not depend on the concrete decoder crates; the application wires backend handles and materializers together. The refactor guardrails enforce these dependency boundaries.
CPU readback is used by integration tests to inspect rendered output; it is not a production CPU rendering fallback.
Decoded metadata and the frame contract reach the rendering boundary together. GPU shaders perform YUV-to-RGB conversion and, on supported HDR paths, BT.2446-C HDR → SDR tone mapping. The verified P010 path converts BT.2020/PQ input to SDR BT.709 output. Native HDR monitor output is not implemented.
The video renderer owns color processing, aspect/orientation handling, and viewport clipping. The shell owns the WGPU surface/device and final video/UI composition, submission, and presentation. It preserves egui texture lifetimes through submission. A frame submitted to a headless adapter proves less than successful presentation on a particular physical display; acceptance reports distinguish them.
Audio owners decode and process PCM and drive the production audio clock. The playback core coordinates packet windows, audio/video timing, seek settlement, and EOF/drain behavior. Video, audio, and network sources can progress asynchronously; queue admission and restore must use the appropriate consumer evidence rather than a generic ready flag.
Diagnostics are produced at their owning boundaries: transport request/byte accounting, decode/completion status, seek timing, audio progress, and renderer submissions. The app presents those observations; it must not infer successful playback solely from a URL opening or a decoder returning a frame.
The application-contract matrix maps editable settings to owners and intent-based application mechanisms. The app transaction adapter connects those contracts to runtime owners.
Applying settings validates the draft, checks generation/busy conditions, applies runtime routes in order, persists atomically, and finalizes committed state. Failure compensates completed work in reverse order; apply and rollback errors remain separately visible. Busy/conflict outcomes preserve the draft for an explicit retry rather than silently queuing changes.
Some changes are in-place updates or visual previews. Others recreate audio output, reopen the source, rebuild the video pipeline, or recreate the renderer. “Settings while running” does not mean every change is interruption-free or every policy affects an already-started operation. Source reconfiguration waits for correlated installation and restore; enqueueing a command is not successful application.
Media files and network manifests are untrusted. Rust ownership and modular APIs reduce the scope of mistakes, but do not eliminate parser bugs, unsafe code, native-library vulnerabilities, or GPU-driver risks.
- Bounded manifest readers, transport budgets, cancellation, and typed errors belong to their source/parser owners.
- Native-to-extractor fallback is owned by the app and restricted to allowlisted causes before installation. Cancellation, ordinary network failures, malformed input, decoder/render failures, and post-install operations must not silently trigger a new extractor path.
- Temporary resolved endpoints, headers, and cookies do not belong in durable playlist state. The exact locator explicitly confirmed by the user is durable identity, so secrets embedded in that locator can still be persisted. Do not share such state without review.
- System yt-dlp configuration/plugins/cookies are trusted external environment, with side effects outside the app's guarantees. FFmpeg is used for software video decode, not as a hidden network or demux fallback.
- Upstream patches preserve their licenses and safety obligations. Dependency checks, FFI review, and hardware validation complement Rust's type system.
Read operational errors, dependency policy, and the panic/invariant policy. Follow SECURITY.md for private vulnerability reporting and its planned launch status.
| Invariant / behavior | Existing enforcement or evidence |
|---|---|
| Concrete backend independence and module size | Architectural guardrails |
| Correct frame representation | Frame-contract tests, render tests |
| Settings apply, failure, compensation, busy/conflict | Settings runtime tests, application contracts |
| Sources reach video/audio consumers | N14A/N14B suites and cross-source regression documented in N15 |
| Seek lands through decode and rendering | CI vertical seek acceptance, manual regressions |
| Actual device playback | N15 hardware evidence; manual hardware workflow |
| Reproducible gates | CI commands |
New boundary tests must exercise absent resources, active fakes/stubs, errors, accounting edges, and state the boundary must not own. Successful playback claims need consumer-level tests. Existing acceptance is scoped to the recorded revision, fixture, and machine; it is not a blanket claim about every GPU, URL, codec, or UI transition.