TASK 3 milestone 1: webcam capture (MediaCapture CPU-first, CameraManager refcount, picker, clip/mirror, schema v2, tests)

This commit is contained in:
2026-08-06 14:35:34 -07:00
parent d97b5d375c
commit 98cdc4b3f4
23 changed files with 1099 additions and 40 deletions
+13 -4
View File
@@ -136,7 +136,15 @@ Preview shows the transition too (WYSIWYG). No wipes/slides/LUTs beyond the four
### Requirements:
1. **Screen** — Windows.Graphics.Capture (WinRT), enumerate displays/windows, picker
2. **Webcam** — MediaCapture (WinRT) with device enumeration
2. **Webcam** — MediaCapture (WinRT SDK projection) with device enumeration — ✅ **milestone 1 done**:
- TFM bumped to `net8.0-windows10.0.19041.0` (app **and** tests) so the WinRT projection resolves from the SDK reference packs — no NuGet package, no capability manifest (unpackaged desktop app)
- `MediaCaptureFrameSource` (CPU-first: `MemoryPreference = Cpu`, BGRA8 via `CreateFrameReaderAsync`), `MediaCaptureCameraEnumerator` (`DeviceInformation.FindAllAsync(DeviceClass.VideoCapture)`)
- `CameraManager`: refcounted by `DeviceId`, one shared `WriteableBitmap` app-wide, dispatcher-coalesced UI updates (~render rate, latest-frame drop), placeholder/`AppLog` + warning on failure
- `CameraPickerDialog` (mirror of `ReuseImageDialog`) — "Searching for cameras…" / list / "No cameras found" states
- One webcam app-wide: Add → Webcam greyed out once one exists ("it's already in your stream" tooltip); persisted `DeviceId` re-acquires after layout load
- Default placement 16:9 **480×270**, bottom-right, 32px margin; drag/resize/selection shared with Image sources
- **Clip shapes: Traditional + Round** (phone view dropped — the 9:16 phone output is the vertical output-crop tier); **mirror**; both persisted in the layout DB (schema v2) and toggled from the source chip
- **Background removal = milestone 2** (ONNX Runtime + DirectML, MediaPipe Selfie Segmentation) — not in this build
3. **Background / Image / Text** — static sources positioned/scaled/opacity
4. **Chat box** — rendered from the live chat poll (right panel is the same feed, raw)
5. **Scene compositing** — per-scene source layering (z-order = sources list order, top-to-bottom
@@ -151,7 +159,7 @@ Preview shows the transition too (WYSIWYG). No wipes/slides/LUTs beyond the four
- **Scenes list:** drag rows to reorder scenes
- **Sources list:** drag rows to reorder sources (this *is* the z-order) — implemented
### Status: 🔶 In progress — scenes/sources UI built (add/reorder/rename, image + background overlays with move/resize/opacity/reuse); real capture/encoding pending
### Status: 🔶 In progress — milestone 1 (webcam) shipped; scenes/sources UI (add/reorder/rename, image + background overlays with move/resize/opacity/reuse) built; screen capture, compositing, and encoding pending
---
@@ -231,8 +239,9 @@ Preview shows the transition too (WYSIWYG). No wipes/slides/LUTs beyond the four
add/remove/reorder, and any source transform change; flush on window close.
5. **Schema**`Scene` (Id, Name, IsHidden, IsChatScene, SortOrder), `Asset` (Id, Hash, Data,
PixelWidth, PixelHeight), `Source` (Id, SceneId FK cascade, AssetId FK, Type, Name, IsEnabled,
X/Y/Width/Height/Opacity, MonitorIndex, DeviceId, SortOrder). `WindowHandle` stays in-memory
(per-session). Save = transactional rewrite; orphaned assets pruned.
X/Y/Width/Height/Opacity, MonitorIndex, DeviceId, ClipShape, IsMirrored, SortOrder) —
`user_version` 2 (v1 → v2 = `ALTER TABLE` adds the two webcam columns). `WindowHandle` stays
in-memory (per-session). Save = transactional rewrite; orphaned assets pruned.
6. **Startup** — load the active file; seed the default five scenes (Starting/Live/BRB/Chat/Ending)
only when the DB is empty.