From 1ca41a4037eec06fafc546d2503cf55678700752 Mon Sep 17 00:00:00 2001 From: Rey Perez Date: Wed, 22 Jul 2026 16:43:18 -0400 Subject: [PATCH] gv_fake_camera: fix spurious 100 ms stall in the frame pacing loop timeout_ms is computed as (next_timestamp_us - g_get_real_time ()) / 1000LL. next_timestamp_us is a guint64, so when the frame deadline has already passed by the time this line runs (scheduler preemption, or a control packet handled right at the deadline), the subtraction underflows to a huge unsigned value and the following clamp turns it into a 100 ms poll timeout instead of 0. Because the fake camera schedules frames on wall-clock-aligned slots (arv_fake_camera_get_sleep_time_for_next_frame), every such stall silently drops ~100 ms worth of frame slots, which are never made up. Streaming a 640x224 Mono16 fake camera at 527 fps, this fired every few seconds and cost ~2 % of the effective frame rate (irregular ~102 ms inter-frame gaps while the median gap stayed exactly at the nominal period). With the signed cast the stalls disappear and the measured rate matches the requested frame rate exactly. Co-Authored-By: Claude Fable 5 --- src/arvgvfakecamera.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/arvgvfakecamera.c b/src/arvgvfakecamera.c index 12dfd9df3..aae5ff409 100644 --- a/src/arvgvfakecamera.c +++ b/src/arvgvfakecamera.c @@ -277,7 +277,10 @@ _thread (void *user_data) do { gint timeout_ms; - timeout_ms = (next_timestamp_us - g_get_real_time ()) / 1000LL; + /* Signed arithmetic: if next_timestamp_us is already in the past, an + * unsigned subtraction underflows and is clamped to a spurious 100 ms + * timeout, stalling the frame pacing. */ + timeout_ms = ((gint64) next_timestamp_us - g_get_real_time ()) / 1000LL; if (timeout_ms < 0) timeout_ms = 0; else if (timeout_ms > 100)