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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant