I made a simple program that acquire data from a camera using the new .Net CVB library.
I configured properly the device and I set the RingBufferLock Mode to ON.
device.Stream.RingBuffer.LockMode = RingBufferLockMode.On;
If I understand correctly from the documentation every time I invoke StreamImage image = await m_stream.WaitAsync()
it place the image acquired in the ring buffer and it locks the buffer for that specific image. It is up to me to unlock the image from the ringbuffer usingimage.Unlock();
, in order to avoid to fill in completely the ringBuffer and don’t have enough space for new images.
This behavior has been described also by @parsd in
IRingBuffer for Task-based Processing “Difference between Cvb.SharedImg and Cvb.Image.IMG”
“
After you have your desired number of buffers, you can set the lock mode to RINGBUFFER_LOCKMODE_ON via the RBLockMode function. This is a manual mode in which the acquisition engine only locks the buffers to write-protect it for the engine. You as the user must unlock the buffer via RBUnlock when you don’t need it anymore. Otherwise no buffers are available anymore after the ring buffer is filled and no new images can be acquired.
”
The strange thing is that after retrieving the image from the ring buffer in this way:
RingBufferImage image = m_stream.RingBuffer[lastAcquiredImageIndex];
and the RingBufferImage goes out of scope, it unlock automatically the slot in the buffer.
Am I doing something wrong?
I copy part of my code, in this way it should be more clear.
private Stream m_stream;
public void InitCamera()
{
var device = LoadCameraDriver();
device.Stream.RingBuffer.LockMode = RingBufferLockMode.On;
device.Stream.RingBuffer?.ChangeCount(NUM_DRIVER_BUFFERS, DeviceUpdateMode.NewDeviceImage);
m_stream = device.Stream;
}
public async Task AcquireData(CancellationTokenSource cts)
{
m_stream.Start();
while (!cts.Token.IsCancellationRequested)
{
using (StreamImage image = await m_stream.WaitAsync())
{
Tuple<IntPtr, int> res = GetBaseAddressAndBuffIndex(cts);
var baseAddress = res.Item1;
var buffIndex = res.Item2;
var processingTask = Task.Run(async () => { await ProcessImage(baseAddress, buffIndex, imgTimeStamp, cts); });
AddTask(PulseCounter, processingTask);
}
}
List<Task> f = m_TaskDictionary.Values.ToList();
Task.WaitAll(f.ToArray());
}
private Tuple<IntPtr, int> GetBaseAddressAndBuffIndex(CancellationTokenSource cts)
{
// last buffer acquired by G2Wait
var lenght = m_stream.RingBuffer.GetAcquisitionSequence().Length;
var lastAcquiredImageIndex = m_stream.RingBuffer.GetAcquisitionSequence()[lenght - 1];
RingBufferImage image = m_stream.RingBuffer[lastAcquiredImageIndex];
if (!image.IsLocked)
{
cts.Cancel();
throw new ScannerException("Ring buffer image has not been locked.");
}
LinearAccessData imageData = image.Planes[0].GetLinearAccess();
return new Tuple<IntPtr,int>(imageData.BasePtr, image.BufferIndex);
}
private async Task ProcessImage(IntPtr baseAddress, int buffIndex, long imgTimeStamp, CancellationTokenSource cts)
{
RingBufferImage image = m_stream.RingBuffer[buffIndex];
if (image.IsLocked)
{
// Do some stuff
imageProcessed
// dispose object
image.Unlock();
await Writer.WriteImageToFileAsync(imageProcessed);
}
else
{
Console.WriteLine("Scanner: {0} - Ring buffer image has not been locked.Buffer Index: {1}", m_Name, buffIndex);
}
}
When GetBaseAddressAndBuffIndex
complete the execution, the ring buffer slot is Unlock automatically, and when I call the function ProcessImage
the buffer is already unlock.
I would expected the buffer being locked and not automatically unlocked by the .Net framework.