Skip to content

Latest commit

 

History

History
94 lines (62 loc) · 12.8 KB

ARCHITECTURE.md

File metadata and controls

94 lines (62 loc) · 12.8 KB

Fastiplayer architecture

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.

Owners and boundaries

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.

Source opening and playback lifecycle

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.

Video frames and GPU ownership

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.

Color and presentation

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, timeline and diagnostics

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.

Settings while running

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.

Trust boundaries

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.

Validation map

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.