# HANDOFF — Session State ## Branch / Commit State **`main`**, working through TASK 21 (media source). Local commits ahead of `origin/main` (not yet pushed — user pushes at agreed checkpoints): - `a1d9751` — docs: ffmpeg decode-contract verification recipe + WSL CLR boundary - `8f49010` — TASK 21 Increment B: FFmpeg rawvideo video decoder -> VideoFrame - `f89b9f9` — docs: default-device audio assumption (README + startup log) - `e8ff4df` — TASK 22: global audio sync offset (positive delay at the mixer out) Prior milestones pushed through `origin/main`: TASK 31 (`3bf053a..670fe3a`), plus the full refactor series (Commit F `3107f92`, Commit G `85893ea`). ## What's In Flight **TASK 21 (media source) — slice 1 step 3 shipped (the session-manager + interface); next open work is the VM wire-in (slice 1 step 4).** Increment A (the `Source` model: `MediaSourceType`, `SourceType.MediaSource`, `MediaPath`/`MediaIsLooping`/`MediaVolume`/`MediaPlaybackState` + LayoutStore persistence) and Increment B (the decoder `MediaVideoSource`) shipped earlier. This session: - Refactored `Services/MediaVideoSource.cs` onto the new `Services/IMediaFrameSource.cs` (`Key`, `FrameAvailable`, `Completed`, `StartAsync`/`StopAsync`; `Start`→`StartAsync`, `FrameReady`→`FrameAvailable`) — behavior preserved, `MediaVideoSourceTests` updated and passing. - Added `Services/MediaVideoSourceManager.cs` — app-wide decode-session ownership refcounted by `MediaPath`, `Func` factory seam, `AcquireAsync`/`ReleaseAsync`/`ReleaseAllAsync`/`GetLatestFrame`, frames coalesced onto the UI dispatcher onto one shared `WriteableBitmap` per file, `MediaFailed` + `PreviewBitmapChanged`. Structural mirror of `ScreenCaptureManager`. - Added `ytLive.Tests/MediaVideoSourceManagerTests.cs` (5 unit + 1 integration: single shared bitmap, coalesce-to-latest). **Verified: all 10 media tests pass (5 manager + 3 reader + 1 decoder integration + 1), build 0 warnings.** Next (slice 1 step 4 — VM wire-in): create `_mediaManager` in the ctor with `path => new MediaVideoSource(path, , , new FfmpegLocator(), new FfmpegDecodeProcess())`, subscribe `OnMediaPreviewBitmapChanged` (set `source.VideoImageSource` for every `IsMediaSource` with that `MediaPath`), add the `Source { IsMediaSource: true, MediaPath: not null }` case to `ResolveOutputFrame` (`MainViewModel.cs:447`), add `or SourceType.MediaSource` to `Source.DisplaySource` (Source.cs:119-121) so media previews route `VideoImageSource`, and dispose the manager on shutdown. Then slices 2 (native-FPS pacing) and 3 (loop). **Landmine:** a stale `testhost` can lock `ytLive.Tests`'s `ytLive.dll` and break `dotnet build` of the test project — kill it first (`cmd.exe /c "taskkill /PID N /F"`) on MSB3027. Full-suite vstest hangs headless (RealAppHost/WASAPI) — only filtered pure tests run in WSL; user verifies the GUI suites on native Windows PowerShell (which may also hang if WASAPI startup blocks — pre-existing, not this change). ## Next 1. Commit slice 1 step 3 (this unit): manager + `IMediaFrameSource` + tests. Commit is already covered by `TASKS.md`/`HANDOFF.md`; this HANDOFF is the shipping doc. 2. Slice 1 step 4: wire `_mediaManager` into the resolver + preview routing (see above). 3. Slice 2: native-FPS pacing (ffprobe FPS probe + per-frame pacing seam). 4. Await user push checkpoint for the pending TASK 22/21 commits. ## The directive (2026-08-31, user) Rewrite the project into functional components to aid AI retrieval — `Services/ChatOverlayLayer.cs` / `SceneGraph.cs` style (owner-state extraction), not line-count chasing. Audio assumption is now an explicit contract (README "Audio Assumption"): the app uses system defaults, never fights Windows device locking, and does not debug user audio issues — OS's problem, not ours.