Phase 7
This commit is contained in:
@@ -2,15 +2,15 @@
|
||||
|
||||
This document expands Phase 7 of [ARCHITECTURE_RESILIENCE_REVIEW.md](/c:/Users/Aiden/Documents/GitHub/video-shader-toys/docs/ARCHITECTURE_RESILIENCE_REVIEW.md) into a concrete design target.
|
||||
|
||||
Phase 4 made the render thread the sole owner of normal runtime GL work, but output timing is still callback-coupled: DeckLink completion callbacks synchronously request render-thread output production before scheduling the next hardware frame. Phase 7 should make backend lifecycle, buffer policy, playout headroom, and recovery explicit.
|
||||
Phase 4 made the render thread the sole owner of normal runtime GL work. Phase 7 Step 4 moved DeckLink completion processing onto a backend worker, so the callback no longer directly waits for render-thread output production. Phase 7 Step 5 added a bounded ready-frame queue inside that worker, so scheduling now consumes completed output frames and falls back explicitly on underrun. Phase 7 should make backend lifecycle, buffer policy, playout headroom, and recovery explicit.
|
||||
|
||||
Phase 5 clarified that live parameter layering stops at final render-state composition. Phase 7 should keep backend lifecycle, output queue ownership, buffer reuse, temporal/feedback resources, and stale-frame/underrun policy outside the persisted/committed/transient parameter model.
|
||||
|
||||
## Status
|
||||
|
||||
- Phase 7 design package: proposed.
|
||||
- Phase 7 implementation: Step 3 complete.
|
||||
- Current alignment: `VideoBackend`, `VideoIODevice`, `DeckLinkSession`, `VideoBackendLifecycle`, and `VideoPlayoutScheduler` exist. Phase 4 removed callback-thread GL ownership, but the DeckLink completion path still waits for render-thread output production.
|
||||
- Phase 7 implementation: Step 6 complete.
|
||||
- Current alignment: `VideoBackend`, `VideoIODevice`, `DeckLinkSession`, `VideoBackendLifecycle`, and `VideoPlayoutScheduler` exist. Phase 4 removed callback-thread GL ownership, Step 4 moved completion processing onto a backend worker, Step 5 uses `RenderOutputQueue` as the ready-frame handoff inside that worker, and Step 6 replaces fixed late/drop skip-ahead with measured recovery decisions.
|
||||
|
||||
Current backend footholds:
|
||||
|
||||
@@ -18,7 +18,7 @@ Current backend footholds:
|
||||
- `DeckLinkSession` owns DeckLink device handles, frame pool creation, preroll, keyer configuration, and scheduled playback.
|
||||
- `VideoPlayoutPolicy` names current frame pool, preroll, ready-frame, underrun, and catch-up policy defaults.
|
||||
- `RenderOutputQueue` names the future bounded ready-output-frame handoff and has pure queue tests.
|
||||
- `VideoPlayoutScheduler` owns basic schedule time generation and simple late/drop skip-ahead behavior.
|
||||
- `VideoPlayoutScheduler` owns schedule time generation, completion indexing, late/drop streaks, ready-queue pressure input, and measured recovery decisions.
|
||||
- `OpenGLVideoIOBridge` is the current adapter between `VideoBackend` and `RenderEngine`.
|
||||
- `HealthTelemetry` receives some signal, render, and pacing stats.
|
||||
|
||||
@@ -28,7 +28,7 @@ The current output path works only while render/readback stays comfortably insid
|
||||
|
||||
The resilience review calls this the main remaining live-resilience risk after Phase 4:
|
||||
|
||||
- output playout is still effectively render-on-demand from the DeckLink completion callback
|
||||
- output playout is still effectively filled on demand by a backend completion worker, but scheduling now consumes a bounded ready-frame queue
|
||||
- buffer pool size and preroll depth are not sourced from one policy
|
||||
- late/dropped recovery is a fixed skip rule
|
||||
- backend lifecycle is imperative rather than represented as explicit states
|
||||
@@ -260,22 +260,36 @@ Stop producing frames directly in the completion callback path.
|
||||
|
||||
Transitional target:
|
||||
|
||||
- callback wakes/schedules a backend worker
|
||||
- worker consumes ready frames
|
||||
- [x] callback wakes/schedules a backend worker
|
||||
- [x] worker consumes ready frames
|
||||
|
||||
Final target:
|
||||
|
||||
- callback only records, recycles, dequeues, schedules
|
||||
|
||||
Current implementation:
|
||||
|
||||
- `VideoBackend::HandleOutputFrameCompletion(...)` now enqueues completion work and wakes an output-completion worker.
|
||||
- The output-completion worker drains pending completions and runs the existing render/schedule path.
|
||||
- This preserves behavior while removing the direct callback-thread wait on render-thread output production.
|
||||
- Step 5 now makes this worker consume ready frames from `RenderOutputQueue`; Step 4 remains the boundary that keeps output completion callbacks from doing render production directly.
|
||||
|
||||
### Step 5. Make Render Produce Ahead
|
||||
|
||||
Teach render/output code to keep the ready queue filled to target headroom.
|
||||
|
||||
Initial target:
|
||||
|
||||
- render thread produces on demand until queue has target depth
|
||||
- callback does not synchronously wait for fresh render
|
||||
- stale/black fallback is explicit on underrun
|
||||
- [x] render thread produces on demand until queue has target depth
|
||||
- [x] callback does not synchronously wait for fresh render
|
||||
- [x] stale/black fallback is explicit on underrun
|
||||
|
||||
Current implementation:
|
||||
|
||||
- The backend output-completion worker fills `RenderOutputQueue` to `VideoPlayoutPolicy::targetReadyFrames`.
|
||||
- Scheduling now pops a ready frame from `RenderOutputQueue` instead of directly scheduling the freshly rendered frame.
|
||||
- If no ready frame can be produced, the worker schedules an explicit black fallback frame and reports degraded lifecycle state.
|
||||
- This is still demand-filled by the backend worker; a future pass can make render production more proactive or timer/pressure driven.
|
||||
|
||||
### Step 6. Replace Fixed Late/Drop Recovery
|
||||
|
||||
@@ -283,8 +297,16 @@ Replace fixed `+2` schedule-index recovery with measured lag/headroom accounting
|
||||
|
||||
Initial target:
|
||||
|
||||
- track scheduled index, completed index, queue depth, late streak, drop streak
|
||||
- recovery decisions use measured lag
|
||||
- [x] track scheduled index, completed index, queue depth, late streak, drop streak
|
||||
- [x] recovery decisions use measured lag
|
||||
|
||||
Current implementation:
|
||||
|
||||
- `VideoPlayoutRecoveryDecision` reports completion result, completed index, scheduled index, ready queue depth, scheduled lead, measured lag, catch-up frames, late streak, and drop streak.
|
||||
- `VideoPlayoutScheduler::AccountForCompletionResult(...)` now accepts ready queue depth and returns a recovery decision.
|
||||
- Recovery is measured from late/drop streaks, scheduled lead, and ready queue pressure, then capped by `VideoPlayoutPolicy::lateOrDropCatchUpFrames`.
|
||||
- `VideoBackend` passes the current ready queue depth into the video device completion-accounting call.
|
||||
- `VideoPlayoutSchedulerTests` cover measured late recovery, measured drop recovery, policy caps, completed-index tracking, and streak clearing.
|
||||
|
||||
### Step 7. Route Backend Health Structurally
|
||||
|
||||
@@ -339,10 +361,10 @@ Phase 7 can be considered complete once the project can say:
|
||||
|
||||
- [x] backend lifecycle states and transitions are explicit
|
||||
- [x] playout policy owns preroll, pool size, headroom, and underrun behavior
|
||||
- [ ] output callbacks no longer synchronously wait for render production
|
||||
- [ ] render produces completed output frames into a bounded queue
|
||||
- [ ] underrun behavior is explicit and observable
|
||||
- [ ] late/drop recovery is measured rather than fixed skip-only
|
||||
- [x] output callbacks no longer synchronously wait for render production
|
||||
- [x] render produces completed output frames into a bounded queue
|
||||
- [x] underrun behavior is explicit and observable
|
||||
- [x] late/drop recovery is measured rather than fixed skip-only
|
||||
- [ ] backend health reports lifecycle, queue, underrun, late, and dropped state
|
||||
- [ ] queue/lifecycle/scheduler behavior has non-DeckLink tests
|
||||
|
||||
|
||||
Reference in New Issue
Block a user