Where does the image point to using RGBufferSeq with NumBuffers-1?

Hello,

I am still a little bit confused what RBBufferSeq and using NumBuffers - 1.

The original question was:

Does RBBufferSeq return the oldest image or oldest unprocessed image in the buffer when the sequence number is BufferCount-1?

There the answer was:

The ring buffer uses a locking mechanism which is dependent on the RINGBUFFER_LOCKMODE.
By default the lock mode is set to RINGBUFFER_LOCKMODE_AUTO: In that case a buffer is locked, once it is filled with a new image from the camera and unlocked upon retrieval when using the function G2Wait. After being unlocked the buffer is free to be filled with new images by the camera.
The function G2Wait returns the oldest locked buffer (and unlocks that buffer afterwards).

Alternative lock modes are:
RINGBUFFER_LOCKMODE_OFF (all buffers are always unlocked and can be used to be refilled with new images anytime)
RINGBUFFER_LOCKMODE_ON (unlocking of buffers have to be done manually with RBUnlock)

In the function RBBufferSeq the IBufferIndex is relative to the last call of G2Wait.
IBufferIndex = 0: The returned buffer is identical to the last one received with the G2Wait call.
IBufferIndex = 1: The returned buffer contains the previous image. This is useful for arithmetic oparations (eg. Image subtraction)

IBufferIndex = bufferCount -1: Content of the returned buffer might be undefined, depending on the application

The usage of this function is very dependent on the application. In the worst case the “oldest Buffer”( bufferCount -1) might be the newest buffer.

This makes sense. But I am not sure where the bufferCount -1 actually points to. Please consider following scenarios.

Hereby assume:

  • blue buffers have been read and are unlocked
  • green buffers are acquired but have not been called yet by G2Wait (they are locked).
  • red buffer is the last buffer read by G2Wait.
  • white buffers have never been written yet by acqusition (e.g., as the acquisition has just started and the buffer hasn’t been filled yet).

Questions:

  • The G2Wait call (IBufferIndex = 0) points to buffer 3. So far so good.
  • IBufferIndex = 1 would point to buffer 2.
  • … and so on…
  • Does IBufferIndex = bufferCount - 1 return the next buffer after G2Wait, e.g., buffer 4 for both scenarios?
  • Or does it differ depending which buffers have been written beforehand and which buffers are currently locked?

Thank you for your help.

Amicelli

2 Likes

This is kind of confusing for me as well. I would assume that if your NumBuffers is 10 and you call RBBufferSeq with 9, you get the 10th image acquired, assuming they are all locked. I would also assume the buffer has to be valid and has to hold an image. So, I’m not sure if you can successfully call RBBufferSeq with 9 if only 3 calls of G2Wait have passed.

But, the manual states “NumBuffers-1” returns the “oldest” image. For me, the oldest image might be the image that has stayed in the ring buffer the longest. That means, that is the image, that sits right before the most recent unlocked image in the ring buffer, right? Maybe the manual is referring to call RBBufferSeq with “-1”?

Hi Frank,

would it possible to update the documentation for future reference? Furthermore, would you mind looking into the source or ask someone to see what it actual mean? That would be really beneficial as it would clarify what it actually does…

Amicelli

Sure, I will try to verify with the developer and then improve the manual correspondingly. But, as mentioned, I’m not perfectly sure how it works. Maybe another user can provide more insight.

I have a clarification for the “NumBuffers-1 is the index of the oldest image” - part.

The scenarios illustrated in your initial post are for a case of continues acquisition with auto lock mode, right?

The green buffers are pending and cannot be reached by RBBuffSeq() in general. Only on buffers with which G2Wait() has been called on already can be accessed with RBBuffSeq(). Otherwise the access is undefined.

For your scenario 1, this is the case.

For scenario 2 the index “NumBuffers-1” would try to return the buffer index labeled “4” if you have at least called G2Wait() NumBuffer times. But, there is also no valid image at this location since G2Wait() has not been called yet for this buffer, it would have to be blue to work properly.


For most use cases, there is no real application for “NumBuffers-1”. But consider this:

RAM recording scenario: where the lock mode is on and you fill the whole buffer once to then do processing on it offline.

Since index “0” is the most recent image (as stated in the manual), and you want to go through the locked ring buffer in order of acquisition, you have to iterate RBBuffSeq() from “NumBuffers -1” to “0”.

In a case of “10” buffers and locked mode = on, you would iterate from “9” to “0” after 10 images have been acquired (as in G2Wait has been called 10 times). While “9” being the oldest image, “8” the one that has been acquired right after the oldest, “7” being the next image in line and so on.

That makes “1” the image right before the most recent call of G2Wait() while RBBufferSeq called with “0” represents the same image of the most recent G2Wait() call itself.

All above mentioned only applies, if the buffer is full.

(Mods, if this leads to more confusion, please just delete. :confounded:)

2 Likes

@Amicelli, I understand your confusion. :smirk: The cited answer mixes two concepts:

  • Buffer fill order
  • Buffer lock state

RBBufSeq does not care about the RINGBUFFER_LOCKMODE. Although the lock mode may have an impact on the fill order. RBBufSeq just returns the order in which the buffers were filled by the acquisition engine seen from your, the users, perspective.

As filling the buffers is an independent, asynchronous operation, the information given by RBBufSeq is always dependent on G2Wait (otherwise it might change inbetween two calls of RBBufSeq, even if G2Waitwas not called - and this would be undesirable). So as @Frank wrote: only buffers handled via G2Wait are seen by RBBufSeq.

The valid range for the sequenceIndex is:

int minSequenceIndex = 0;
int maxSequenceIndex = min(deliveredBuffers, numBuffers) - 1;

maxSequenceIndex denotes the oldest image buffer delivered to you being still ‘available’. minSequenceIndex is the current driver image (the newest delivered image). Everything outside this range is undefined.

Getting the deliveredBuffers stat.

If your driver supports G2INFO_NumBuffersDelivered via G2GetGrabStatus, this would be it. Otherwise you need to count the number of G2Wait calls yourself.

As a side note: Be very careful accessing unlocked buffers! For pure display-purposes this can be fine if you can live with possible artifacts. Processing on unlocked buffers yields undefined behavior as this buffer can be overwritten any time by the acquisition engine! Thus using this functionality with RINGBUFFER_LOCKMODE_AUTO or RINGBUFFER_LOCKMODE_OFF is dangerous. It is very useful with RINGBUFFER_LOCKMODE_ON, though (as described in the RAM-recording example by @Frank).

3 Likes

Thanks @Frank and @parsd :grinning:
This makes it much clearer…