UYVY backend
All checks were successful
CI / React UI Build (push) Successful in 11s
CI / Native Windows Build And Tests (push) Successful in 2m22s
CI / Windows Release Package (push) Has been skipped

This commit is contained in:
Aiden
2026-05-30 19:16:16 +10:00
parent d0b1f63524
commit f0f8b080ca
30 changed files with 733 additions and 239 deletions

View File

@@ -13,8 +13,9 @@ RenderThread
owns a hidden OpenGL context
polls the oldest ready input frame without waiting
uploads input frames into a render-owned GL texture
renders simple BGRA8 motion at selected cadence
queues async PBO readback
renders at selected cadence
optionally GPU-packs the output target into UYVY8
queues async PBO readback for the selected system-frame format
publishes completed frames into SystemFrameExchange
InputFrameMailbox
@@ -47,17 +48,17 @@ Startup builds a small output preroll reserve before DeckLink scheduled playback
Included now:
- generic video output edge contract with DeckLink as the current implementation
- generic video output edge contract with DeckLink and NDI output implementations
- optional DeckLink input edge with BGRA8 capture or raw UYVY8 capture decoded on the render thread
- non-blocking startup when DeckLink output is unavailable
- hidden render-thread-owned OpenGL context
- simple smooth-motion renderer
- BGRA8-only output
- BGRA8 and render-thread-packed UYVY8 system-memory output
- non-blocking three-frame FIFO input mailbox for render
- fast contiguous mailbox copy path for matching input row strides
- bounded three-frame input warmup before render cadence starts
- render-thread-owned input texture upload
- async PBO readback
- async PBO readback for the configured system-frame format
- bounded FIFO system-memory frame exchange
- bounded completed-frame output preroll reserve before DeckLink playback, with DeckLink scheduled depth still targeted at four
- conservative DeckLink schedule-lead telemetry and recovery
@@ -103,7 +104,7 @@ Those features should be ported only after the cadence spine is stable.
This tracks parity with `apps/LoopThroughWithOpenGLCompositing`.
- [x] Stable DeckLink output cadence
- [x] BGRA8 system-memory output path
- [x] BGRA8 and UYVY8 system-memory output paths
- [x] Render thread owns its primary GL context
- [x] Output startup warmup before scheduled playback
- [x] Non-blocking startup when DeckLink output is unavailable
@@ -208,6 +209,7 @@ Currently consumed fields:
- `output.device`
- `output.resolution`
- `output.frameRate`
- `output.pixelFormat` (`auto`, `bgra8`, or `uyvy8`)
- `output.keying.external`
- `output.keying.alphaRequired`
- `autoReload`
@@ -215,9 +217,11 @@ Currently consumed fields:
- `previewEnabled`
- `previewFps`
`input.backend` and `output.backend` currently support `decklink` and `none`. Backend creation is routed through the app-side video backend factory, so new concrete backends can be added without making `main` or the render cadence path own their startup details.
`input.backend` and `output.backend` currently support `decklink`, `ndi`, and `none`. Backend creation is routed through the app-side video backend factory, so new concrete backends can be added without making `main` or the render cadence path own their startup details.
When `previewEnabled` is true, the preview window runs on `PreviewWindowThread`. It paints BGRA8 system-memory frames with Win32/GDI after render readback has already completed, so it does not bind GL and does not consume frames from DeckLink output. `previewFps` controls the preview repaint cadence; the default is 60 fps and `config/runtime-host.json` tracks the shipped 59.94 output cadence.
`output.pixelFormat=auto` chooses UYVY8 for DeckLink/NDI output unless alpha output is required, in which case it uses BGRA8. Explicit `uyvy8` requests are rejected back to BGRA8 when alpha is required. V210/YUVA remain explicit unsupported render-readback states until matching render-thread packers exist.
When `previewEnabled` is true, the preview window runs on `PreviewWindowThread`. It paints BGRA8 system-memory frames directly and decodes UYVY8 frames to BGRA for Win32/GDI after render readback has already completed, so it does not bind GL and does not consume frames from video output. `previewFps` controls the preview repaint cadence; the default is 60 fps and `config/runtime-host.json` tracks the shipped 59.94 output cadence.
The loaded config is treated as a read-only startup snapshot. Subsystems that need config should receive this snapshot or a narrowed config struct from app orchestration; they should not reload files independently.
@@ -305,7 +309,7 @@ Input telemetry:
- `renderFrameMs`: most recent render-thread draw duration, excluding completed-readback copy and readback queue work
- `renderFrameBudgetUsedPercent`: most recent render draw time as a percentage of the selected frame budget
- `renderFrameMaxMs`: maximum observed render-thread draw duration for this process
- `readbackQueueMs`: time spent queueing the most recent async BGRA8 PBO readback
- `readbackQueueMs`: time spent queueing the most recent async PBO readback for the selected system-frame format
- `completedReadbackCopyMs`: time spent mapping/copying the most recent completed readback into system-memory frame storage
- `completedDrops`: oldest completed unscheduled system-memory frames dropped because the bounded completed reserve overflowed; this is an app-side reserve drop, not a DeckLink dropped-frame report
- `acquireMisses`: times render/readback could not acquire a writable system-memory frame slot; completed frames waiting for playout are preserved instead of being displaced
@@ -440,7 +444,7 @@ This app keeps the same core behavior but splits it into modules that can grow:
- `render/`: cadence thread, clock, and simple renderer
- `frames/InputFrameMailbox`: non-blocking bounded FIFO CPU input handoff with contiguous-copy fast path for matching row strides
- `render/InputFrameTexture`: render-thread-owned upload of the currently acquired CPU input frame into GL, including raw UYVY8 decode into the shader-visible input texture
- `render/readback/`: PBO-backed BGRA8 readback and completed-frame publication
- `render/readback/`: PBO-backed BGRA8/UYVY8 readback and completed-frame publication
- `render/thread/`: render thread lifecycle, GL startup/cadence loop, metrics, and runtime layer commit mailbox
- `render/runtime/RuntimeRenderScene`: render-thread-owned GL scene for ready runtime shader layers
- `render/runtime/RuntimeShaderPrepareWorker`: shared-context runtime shader program compile/link worker