Getting Started with CVB.Net

RingBuffer Fill Level

This is for when you want to monitor if your processing can keep up with the incoming images. It is based on the post:

Interlude: The IRingBuffer Interface

Vin drivers receive e.g. image data as frames from a camera. This data needs to be stored somewhere: in a buffer, which is a contiguous chunk of memory. A ring buffer is a circular buffer used to store multiple of these buffers. It is called ring buffer, because single buffers are “taken” from it and “returned” if not needed anymore. If you reached the last buffer in the ring buffer, the first one is retrieved – and thus ring closes. With this data structure you can go on acquiring image data for as long as you wish with a finite and constant amount of memory used.

Aside from the ring buffer’s basic properties we use it for these three main reasons:

  1. Enable parallel acquisition and processing

    A ring buffer must have at least three buffers (no really, don’t use less than three buffers :wink:). One is to acquire into, one for the current processing and the last one to be able to switch between the first two without loosing data.

  2. Compensate for varying processing times

    We use more than three buffers to compensate for jitter in processing time. If your processing time is always less than the time between two acquired images, you are fine. But if there are peaks of longer processing time you would loose images. With more buffers you can handle those peaks.

  3. Improve acquisition speed and reduce memory fragmentation

    Memory allocation takes time. Even more so when memory becomes fragmented. The last reason might only be partially intuitive to a .Net developer as .Net has a managed heap. For .Net it “only” takes additional work to compact the memory; for native apps it may mean “out of memory” as no chunk of memory large enough for one image is available anymore.

    Hardware normally does not use the managed heap or at least needs pinned memory. Some hardware even needs to know all these addresses before starting the acquisition.

We will see more of the IRingBuffer interface in later posts. You can do a lot of cool stuff with it.

Most of the vin drivers (including the aforementioned GenICam.vin) support the IRingBuffer interface. This can be queried by the presence of an IRingBuffer object on the Stream:

bool isPresent = device.Stream.RingBuffer != null

Useful Measurement Points

Virtually all vin drivers supporting the IRingBuffer interface have these statistics:

  • StreamInfo.NumBuffersPending

    The number of buffers that have been filled by the acquisition engine that have not been consumed by the client app (via .Wait). When this count is greater than 0, .Wait calls return immediatly.

  • StreamInfo.NumBuffersLocked

    Number of buffers currently locked (meaning not fillable by the acquisition engine). By default this comprises the current image buffer returned by .Wait and all pending image buffers.

These two in combination with the device.Stream.RingBuffer.Count property (or StreamInfo.NumBuffersAnnounced statistic if available) gives you all information necessary to evaluate the acquisition engine status.

If NumBuffersPending increases, you fall behind the acquisition rate. This needn’t be bad if you anticipated this. Reasons can be the processing time peaks mentioned in the IRingBuffer section or you acquire multiple images in bursts to process them as a group.

If at any point in time NumBuffersLocked equals the number of buffers in the IRingBuffer (.Count), you are prone to loose images. If such a buffer overflow happens, NumBuffersLostLocked is increased. This is a counter that is reset on acquisition .Start.

If you want to keep track on the amount of lost images between two .Wait calls you need to store that data and calculate the difference yourself. We don’t do the bookkeeping to be as lean as possible in our acquisition engine (also we don’t know your actual use case: could be simply that, a series of lost frames measured at certain points in time or actually the total number as returned).

Symptoms of too few buffers are, in addition to the lost image data, unexpected drops in acquisition framerate. You can increase the number of buffers either in the driver’s configuration file, which can be found at %CVBCONFIG%Drivers, or programatically via

device.Stream.RingBuffer.ChangeCount(newSize, DeviceUpdateMode.UpdateDeviceImage);

UpdateDeviceImage is the default change mode, NewDeviceImage is used in scenarios when you switch the ring buffer count while still processing image data.

1 Like