From 8460841e8ed2fcc53c1db799e0f375791714e679 Mon Sep 17 00:00:00 2001 From: mikael-lovqvists-claude-agent Date: Sun, 29 Mar 2026 19:32:20 +0000 Subject: [PATCH] Fix no-signal/video fight: only render no-signal after 1s of silence The loop runs at ~200Hz; frames arrive at ~30fps. Most iterations have no pending frame even during active streaming, so no-signal was rendering between real frames. Fix: track last_frame_t and suppress no-signal while a live stream is present (< 1s since last frame). Co-Authored-By: Claude Sonnet 4.6 --- src/node/main.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/src/node/main.c b/src/node/main.c index 0c66865..2676978 100644 --- a/src/node/main.c +++ b/src/node/main.c @@ -187,6 +187,7 @@ struct Display_Slot { /* No-signal animation */ int no_signal_fps; /* 0 → default 15 */ + double last_frame_t; /* wall time of last successfully displayed frame */ double last_no_signal_t; /* Viewer — created and used only on the main thread */ @@ -521,21 +522,25 @@ static void display_loop_tick(struct Node *node) } pthread_mutex_unlock(&d->mutex); + struct timespec _ts; + clock_gettime(CLOCK_MONOTONIC, &_ts); + double now = (double)_ts.tv_sec + (double)_ts.tv_nsec * 1e-9; + if (fdata) { struct Proto_Video_Frame vf; if (APP_IS_OK(proto_read_video_frame(fdata, flen, &vf))) { xorg_viewer_push_mjpeg(d->viewer, vf.data, vf.data_len); + d->last_frame_t = now; } free(fdata); - } else { - /* No live frame — render no-signal animation at configured fps */ - struct timespec ts; - clock_gettime(CLOCK_MONOTONIC, &ts); - double now = (double)ts.tv_sec + (double)ts.tv_nsec * 1e-9; + } + + /* Render no-signal only when stream has been silent for ≥1 s */ + if (now - d->last_frame_t >= 1.0) { double interval = 1.0 / (double)(d->no_signal_fps > 0 ? d->no_signal_fps : 15); if (now - d->last_no_signal_t >= interval) { - /* Wrap to [0, 1000) to preserve float32 fractional precision in shader */ - xorg_viewer_render_no_signal(d->viewer, (float)fmod(now, 1000.0), 80.0f); + /* Wrap to [0, 1000) to preserve float32 fractional precision */ + xorg_viewer_render_no_signal(d->viewer, (float)fmod(now, 1000.0), 80.0f); d->last_no_signal_t = now; } }