Skip to content

v0.26.2

Choose a tag to compare

@github-actions github-actions released this 18 Sep 00:09
· 80 commits to main since this release
b0bdb5c

What changed and why

A single grab now recognises its own frame by a clock we set, not by a number the device owns.

GrabOne has to tell the frame it asked for from one that merely turned up — a leftover from an
earlier acquisition. It did that by frame number: accept only a frame newer than the last one
emitted. That works only while the numbering keeps running, and the device decides when it
restarts
. Two cameras, two answers, both measured:

frame ids, stopping after each grab not stopping
Basler acA2500-14gm 1, 2, 3, 4 5, 6, 7, 8
Crevis MG-A320K-35 (fw 3.6.2.9) 1, 1, 1, 1 1, 2, 3, 4

Since 0.25.2 every grab ends with AcquisitionStop, so on the second camera every grab starts a new
numbering epoch. 0.26.1 papered over that by discarding the baseline at each stop, which fixed the
common case and left one hole: the queue drain runs before the next AcquisitionStart and re-armed
the baseline with a number from the previous epoch, so any grab that found something to drain
could fail the same way.

The case that settles it, measured on the line: a grab whose stale frames carried ids 1, 2, 3, 4
and whose own frame carried id 1. No comparison of numbers can separate those.

So the grab now latches the device's own clock immediately before AcquisitionStart and discards
any frame stamped earlier than that line. There is no threshold and no assumption about numbering.
The registers used — GevTimestampControlLatch and GevTimestampValue — are standard GigE Vision
bootstrap registers, not a vendor extension. A camera that supplies no usable clock falls back to the
previous frame-number behaviour, unchanged.

Three premises were measured on both camera families before relying on them:

  • The frame header's stamp and the latched register are the same clock. Latch, grab, latch again:
    the frame's timestamp lands between the two latches.
  • It is not a time-of-day value that would wrap at midnight. The observed counters held 13.6 days
    (Basler, 125 MHz ticks) and over a day (Crevis, 66.7 MHz) since their epoch.
  • It actually rejects a stale frame. With an old frame deliberately left in the queue, the latch
    separates it from the new one in a single comparison.

One thing worth stating plainly, because it changes how this fix can be maintained: the failing
scenario can now be reproduced on any camera.
A stale frame sitting in the queue needs no
renumbering device to create, so the guard can be exercised here rather than only where the defect
happened to show. The old guard could only be tested on hardware that renumbers.

The camera-state line logged at open now ends with grabKey=deviceClock or grabKey=frameId, so the
log says which rule a given camera is actually running under.

Also

Four XML-documentation warnings are fixed — three of them introduced in 0.26.0, including a cref to
a member that does not exist. They were missed because the build output was being filtered and
because an incremental build reports no warnings when it recompiles nothing.

Version

0.26.2 — patch. No public API change; one defect fix plus diagnostics.

Checks

  • dotnet build --no-incremental in the default configuration reports 0 warnings
  • main is an ancestor of this branch (the release-pr-guard job verifies it)
  • the tag will be created on the merge commit, main merged back into dev afterwards, and dev bumped to the next -dev version