diff --git a/apps/RenderCadenceCompositor/README.md b/apps/RenderCadenceCompositor/README.md index 29f33bf..404373b 100644 --- a/apps/RenderCadenceCompositor/README.md +++ b/apps/RenderCadenceCompositor/README.md @@ -34,7 +34,7 @@ DeckLinkOutputThread never renders ``` -Startup warms up real rendered frames before DeckLink scheduled playback starts. When DeckLink input is available, startup also waits briefly for initial input frames before the render thread starts so the first render ticks are deliberate rather than lucky. +Startup warms up real rendered frames before DeckLink scheduled playback starts. When DeckLink input is available, startup also waits briefly for two ready input frames before the render thread starts so the first render ticks are deliberate rather than lucky. ## Current Scope @@ -48,7 +48,7 @@ Included now: - BGRA8-only output - non-blocking latest-frame input mailbox - fast contiguous mailbox copy path for matching input row strides -- bounded input warmup before render cadence starts +- bounded two-frame input warmup before render cadence starts - render-thread-owned input texture upload - async PBO readback - latest-N system-memory frame exchange @@ -124,7 +124,7 @@ This tracks parity with `apps/LoopThroughWithOpenGLCompositing`. - [x] UYVY8 input capture with render-thread GPU decode to shader input texture - [x] Latest-frame CPU input mailbox - [x] Fast contiguous input mailbox copy when source/destination stride matches -- [x] Bounded input warmup before render cadence starts +- [x] Bounded two-frame input warmup before render cadence starts - [x] Render-owned input texture upload - [x] Runtime shaders receive input through `gVideoInput` - [x] Live DeckLink input bound to `gVideoInput` @@ -254,7 +254,7 @@ Startup order is: 2. try to attach DeckLink input for the configured input mode 3. prefer BGRA8 capture, otherwise accept raw UYVY8 capture and configure the mailbox for UYVY8 bytes 4. start `DeckLinkInputThread` -5. wait briefly for initial input warmup frames before starting render cadence +5. wait briefly for two ready input warmup frames before starting render cadence 6. leave input absent if discovery, setup, format support, or stream startup fails `DeckLinkInput` and `DeckLinkInputThread` are deliberately narrow. They capture BGRA8 frames directly or raw UYVY8 frames into `InputFrameMailbox`; they do not call GL, render, preview, screenshot, shader, or output scheduling code. UYVY8-to-RGBA decode happens later inside the render-thread-owned input texture upload path, so the DeckLink callback stays a capture/copy edge only. The mailbox uses one contiguous copy when the capture row stride matches the configured mailbox row stride, and falls back to row-by-row copy only for padded or mismatched frames. Unsupported input modes or formats outside BGRA8/UYVY8 are reported explicitly and treated as an unavailable edge rather than silently converted. diff --git a/apps/RenderCadenceCompositor/RenderCadenceCompositor.cpp b/apps/RenderCadenceCompositor/RenderCadenceCompositor.cpp index 0f4983e..095400a 100644 --- a/apps/RenderCadenceCompositor/RenderCadenceCompositor.cpp +++ b/apps/RenderCadenceCompositor/RenderCadenceCompositor.cpp @@ -50,7 +50,7 @@ bool WaitForInputWarmup(InputFrameMailbox& mailbox, std::size_t targetReadyFrame while (std::chrono::steady_clock::now() - start < timeout) { const InputFrameMailboxMetrics metrics = mailbox.Metrics(); - if (metrics.readyCount >= targetReadyFrames || metrics.submittedFrames >= targetReadyFrames) + if (metrics.readyCount >= targetReadyFrames) return true; std::this_thread::sleep_for(std::chrono::milliseconds(2)); } @@ -139,9 +139,9 @@ int main(int argc, char** argv) deckLinkInputStarted = true; RenderCadenceCompositor::Log("app", "DeckLink input edge started for " + inputVideoMode.displayName + "."); RenderCadenceCompositor::Log("app", "Waiting for DeckLink input warmup frames."); - constexpr std::size_t kInputWarmupFrames = 2; - constexpr std::chrono::milliseconds kInputWarmupTimeout(500); - if (WaitForInputWarmup(inputMailbox, kInputWarmupFrames, kInputWarmupTimeout)) + constexpr std::size_t kInputStartupBufferedFrames = 2; + constexpr std::chrono::milliseconds kInputWarmupTimeout(1000); + if (WaitForInputWarmup(inputMailbox, kInputStartupBufferedFrames, kInputWarmupTimeout)) { const InputFrameMailboxMetrics metrics = inputMailbox.Metrics(); RenderCadenceCompositor::Log(