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 <noreply@anthropic.com>
This commit is contained in:
2026-03-29 19:32:20 +00:00
parent 30ad5fbeae
commit 8460841e8e

View File

@@ -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;
}
}