Skip to content

gv_fake_camera: fix spurious 100 ms stall in the frame pacing loop - #1089

Open
rperez45 wants to merge 1 commit into
AravisProject:mainfrom
rperez45:fix-fake-camera-timeout-underflow
Open

gv_fake_camera: fix spurious 100 ms stall in the frame pacing loop#1089
rperez45 wants to merge 1 commit into
AravisProject:mainfrom
rperez45:fix-fake-camera-timeout-underflow

Conversation

@rperez45

Copy link
Copy Markdown

Bug

In ArvGvFakeCamera's _thread loop, the poll timeout is computed as:

timeout_ms =  (next_timestamp_us - g_get_real_time ()) / 1000LL;

next_timestamp_us is a guint64. If the frame deadline has already passed by the time this line executes — a scheduler preemption between computing the deadline and polling, or a GVCP control packet (e.g. a heartbeat) handled right at the deadline — the subtraction underflows to a huge unsigned value, and the timeout_ms > 100 clamp just below turns it into a spurious 100 ms poll instead of 0.

Because frames are scheduled on wall-clock-aligned slots (arv_fake_camera_get_sleep_time_for_next_frame returns period - now % period), the ~100 ms of missed frame slots are silently skipped, never made up.

Observed effect

Streaming a 640×224 Mono16 fake camera at 527 fps (GigE Vision hyperspectral camera emulation), the fake camera consistently delivered ~2 % under the requested rate. Receiver-side inter-frame timing showed the signature: the median gap was exactly the nominal period (1897 µs), but irregular ~102 ms stalls appeared every few seconds:

steady-state rate: 514.67 fps (nominal 527)
inter-frame us: mean=1943.0 p50=1897 p99=1945 max=102242
stalls >10ms: 7 in 30 s, each ~102 ms  (= 100 ms poll + ramp to next slot)
time lost to stalls: 0.697 s of 29.487 s (2.36 %)

Fix

Cast to signed before subtracting, so an expired deadline yields a negative value and takes the existing timeout_ms < 0 → 0 path:

timeout_ms = ((gint64) next_timestamp_us - g_get_real_time ()) / 1000LL;

After the fix, same probe:

steady-state rate: 525.19 fps   (527.15 is exact nominal: the period
inter-frame us: p50=1897 max=6782    register truncates 1897.5 → 1897 µs)
stalls >10ms: 0

and a 4-stream 60 s run measured 527.1–527.2 fps on all four fake cameras with zero stalls.

🤖 Generated with Claude Code

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 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

1 participant