This class represents the Camera Link grabber module.
One instance of this class controls one or two Camera Link input connectors which are physically combined on the same hardware. Depending on the hardware and firmware, Camera Link Base (single or dual channel), Medium, Full and Deca configurations are supported. The function GetNumberOfInputs() can be used to determine which configurations are available.
This example demonstrates a simple use case for acquiring images from a camera. The following assumptions are made:
VIB::CameraLinkIn cameraLink;
void *pBuffer = NULL;
const unsigned short Width = 640;
const unsigned short Height = 480;
const unsigned int channel = 0;
const unsigned int buffers = 4;
bool isImgValid;
// Open the first CameraLinkIn device
cameraLink.Open(0);
// set the AOI size and the pixel format
cameraLink.ConfigureCLInput(
channel,
Width,
Height);
// allocate image buffers and add them to the acquisition queue
for (unsigned int i = 0; i < buffers; i++)
{
cameraLink.AllocateImageBuffer(channel, &pBuffer);
cameraLink.AddImageBufferForCapturing(channel, pBuffer);
}
// acquisition loop
while (running)
{
// wait for a new image using a timeout of 1000 ms
cameraLink.WaitForImageBuffer(channel, 1000, &pBuffer, isImgValid);
if (pBuffer != NULL)
{
if (isImgValid)
{
// work with the buffer
ProcessImage(pBuffer);
}
else
{
printf("Frame is invalid\n");
}
// add the buffer into the acquisition queue again
cameraLink.AddImageBufferForCapturing(channel, pBuffer);
}
else
{
printf("Frame timeout\n");
}
}
// Abort image acquisition
cameraLink.AbortBufferUsage(channel);
// Get image buffers from the library and release them
while (true)
{
cameraLink.WaitForImageBuffer(channel, 0, &pBuffer, isImgValid);
if (pBuffer == NULL)
break;
cameraLink.FreeImageBuffer(channel, pBuffer);
}
Please note that error checking was removed to keep the code as simple as possible. |
The Camera Link standard defines four output signals which are mainly used for triggering cameras, also known as CC-Lines. The state of every line can be individually configured with ConfigureCC(). The Multiplexer output signals are available as source for the CC lines.
The internal TriggerGenerator is configured to generate a 10 Hz signal and then used as camera trigger on the CC1 line. VIB::Multiplexer multiplexer;
VIB::TriggerGenerator triggerUnit;
VIB::CameraLinkIn cameraLink;
const unsigned int channel = 0;
// Open devices: Multiplexer, Trigger Unit and Camera Link
multiplexer.Open();
triggerUnit.Open();
cameraLink.Open();
// Trigger Unit: configure a signal generator to 10Hz and connect it to output 0 of the unit
triggerUnit.ConfigureSet("GenA_tLow=50ms GenA_tHigh=50ms TrigOut0_Mux=GenA");
// Multiplexer: connect multiplexer output 0 to the trigger unit
multiplexer.ConnectOutput(0, VIB::Multiplexer::MUX_SRC_TRIGGEN_OUT0);
// Connect the CC1 line to the multiplexer output
cameraLink.ConfigureCC( channel,
1, // CC-line index for CC1
VIB::CameraLinkIn::CL_IN_CC_SRC_MUX_OUT0, //source for the CC line
false ); // no inversion of the signal
// ...
Please note that error checking was removed to keep the code as simple as possible. |
The internal TriggerGenerator is configured to divide the encoder signal and then use it as camera trigger on the CC1 line. VIB::Multiplexer multiplexer;
VIB::TriggerGenerator triggerUnit;
VIB::CameraLinkIn cameraLink;
const unsigned int channel = 0;
// Open devices: Multiplexer, Trigger Unit and Camera Link
multiplexer.Open();
triggerUnit.Open();
cameraLink.Open();
// Multiplexer: make encoder A/B available for the trigger unit
multiplexer.ConnectOutput(0, VIB::Multiplexer::MUX_SRC_SYNC_0);
multiplexer.ConnectOutput(1, VIB::Multiplexer::MUX_SRC_SYNC_1);
// Trigger Unit: use DividerA to reduce the frequency of the encoder signal by 10
triggerUnit.ConfigureSet("DividerA=10,TrigIn0/1_Both");
// Trigger Unit: connect divider output to output 0 of the unit
triggerUnit.ConfigureSet("MuxIntern0=DividerA TrigOut0_Mux=TrigIntern0");
// Multiplexer: connect multiplexer output 2 to the trigger unit
multiplexer.ConnectOutput(2, VIB::Multiplexer::MUX_SRC_TRIGGEN_OUT0);
// Connect the CC1 line to the multiplexer output
cameraLink.ConfigureCC( channel,
1, // CC-line index for CC1
VIB::CameraLinkIn::CL_IN_CC_SRC_MUX_OUT2, //source for the CC line
false ); // no inversion of the signal
Please note that error checking was removed to keep the code as simple as possible. |
Three counters can be enabled in order to embed additional information at the beginning of each frame or each line for line scan cameras. The counters are controlled by the InFlags parameter for ConfigureCLInput():
The image counter can be used for detection of dropped camera frames or lines which are caused by insufficient acquisition buffers. With area scan cameras, the image counter increases with every frame received from the camera (FVAL signal).
The CC1 trigger counter is used in triggered mode for detection of ignored trigger events, for example when the trigger signal on CC1 is arriving too fast for the camera.
The timestamp value is based on a micro-second counter which is inserted by the FPGA during reception of the frame start or line start on the Camera Link interface.
If a counter is enabled, the original pixel data from the camera is overwritten by the corresponding counter value. The location of the counter values is fixed, see example below.
bool checkCounters = false;
unsigned short frameCounter[2];
unsigned short trgCounter[2];
unsigned int timestamp[2];
...
// enable all counters
cameraLink.ConfigureCLInput(
channel,
Width,
Height);
...
while (running)
{
bool isImgValid;
// wait for a new image using a timeout of 1000 ms
cameraLink.WaitForImageBuffer(channel, 1000, &pBuffer, isImgValid);
if (pBuffer != NULL)
{
if (isImgValid)
{
// read the counter values from the beginning of the image:
frameCounter[0] = ((unsigned short *)pBuffer)[0];
trgCounter[0] = ((unsigned short *)pBuffer)[1];
timestamp[0] = ((unsigned int *)pBuffer)[1];
if (checkCounters)
{
unsigned short counterDiff;
// check the received sensor frames
counterDiff = frameCounter[0] - frameCounter[1];
if (counterDiff != 1)
printf("%u camera frames dropped\n", counterDiff);
// check the trigger counter
counterDiff = trgCounter[0] - trgCounter[1];
if (counterDiff != 1)
printf("%u CC1 trigger events dropped\n", counterDiff);
printf("Frame period: %u us\n", timestamp[0] - timestamp[1]);
}
else
{
// delayed start of counter check
checkCounters = true;
}
// store values for the next cycle
frameCounter[1] = frameCounter[0];
trgCounter[1] = trgCounter[0];
timestamp[1] = timestamp[0];
}
else
{
printf("Frame is invalid\n");
}
// add the buffer into the acquisition queue again
cameraLink.AddImageBufferForCapturing(channel, pBuffer);
}
else
{
printf("Frame timeout\n");
}
}
Please note that no error checking is performed in the examples in order to simplify the code. |
The Rs232 device can be used to enable communication with the connected camera through the Camera Link cable.
When using a Windows platform, the Serial Communications API defined by the Camera Link specification can also be used. This allows access by third party configuration tools provided by the camera manufacturer for example.
The Windows SDK installer configures the following registry values for finding the required DLL clserima.dll, existing registry values will not be overwritten:
The SDK installer copies the 32-bit and 64-bit DLL variants of clserima.dll to the locations specified by the registry values.
The registry values are evaluated by the middleware DLL named clallserial.dll. This DLL searches for frame grabber DLLs in the specified directory, for example clserima.dll.
clallserial.dll provides a common interface for camera control applications. It is normally provided by the camera manufacturer, or it can be downloaded here: CLALLSERIAL Project.
Hardware | Precondition | Supported capabilities | ||
---|---|---|---|---|
Library Version | FPGA Version | Camera Link Deca | Unused byte for 24 bit RGB | |
PCIe Camera Link Card | 1.6.5.7 | SYST_CL: 1.0.0.11 | yes | 0xff |
1.6.4.0 | SYST_CL: 1.0.0.6 | no | 0xff | |
VisionBox AGE-X2 | 1.6.0.0 | SYST_BASEBOARD: 1.0.0.24 SYST_CL: 1.0.0.7 | no | 0xff |
SYST_BASEBOARD: 1.0.0.24 SYST_CL: 1.0.0.2 | random | |||
VisionBox AGE-X5 | 1.6.8.0 | SYST_BASEBOARD: 1.0.0.45 SYST_CL: 1.0.0.12 | yes | 0xff |
VisionCam XM | 1.6.4.0 | SYST_BASEBOARD: 1.0.0.30 | no | 0xff |
Public Types | |
enum | CC_SOURCE |
The source signals for the Camera Link CC lines, used by ConfigureCC() More... | |
enum | INMODE_FLAGS |
Special or additional configuration modes, used by ConfigureCLInput() More... | |
enum | INMODE_TYPE |
The data organization on the Camera Link interface, used by ConfigureCLInput() More... | |
enum | MODULE_CONFIGURATION |
Type of Camera Link module configuration ConfigureModule() More... | |
Public Member Functions | |
bool | AbortBufferUsage (const unsigned int ChannelIndex) |
Forces the driver to stop using image buffers. More... | |
bool | AbortWaitingForDMA (const unsigned int ChannelIndex) |
Forces all waiting threads to return from the WaitForImageBuffer() function call. More... | |
bool | AddImageBufferForCapturing (const unsigned int ChannelIndex, void *ptr) |
Adds an image buffer to the acquisition queue for capturing new camera frames. More... | |
bool | AllocateImageBuffer (const unsigned int ChannelIndex, void **pptr) |
Allocates a image buffer for capturing. More... | |
CameraLinkIn () | |
Default constructor for the device object More... | |
bool | ConfigureCC (const unsigned int ChannelIndex, const unsigned int CCIndex, const VIB::CameraLinkIn::CC_SOURCE src, const bool Invert) |
Selects the source for the given CameraLink-CC line. More... | |
bool | ConfigureCLInput (unsigned int ChannelIndex, VIB::CameraLinkIn::INMODE_TYPE InType, unsigned int InFlags, unsigned int AOI_Width, unsigned int AOI_Height, unsigned int AOI_X=0, unsigned int AOI_Y=0) |
Initializes a camera channel. More... | |
bool | ConfigureCLInput (unsigned int ChannelIndex, VIB::CameraLinkIn::INMODE_TYPE InType, unsigned int InFlags, unsigned short Width, unsigned short Height, unsigned short AOI_X, unsigned short AOI_Y, unsigned short AOI_Width, unsigned short AOI_Height) |
Initializes a camera channel. More... | |
bool | ConfigureModule (const VIB::CameraLinkIn::MODULE_CONFIGURATION ModuleConfig) |
Configures the module to the given CL mode. More... | |
bool | FreeImageBuffer (const unsigned int ChannelIndex, void *ptr) |
Frees the specified buffer. More... | |
bool | GetAOI (unsigned int ChannelIndex, unsigned int &AOI_X, unsigned int &AOI_Y, unsigned int &AOI_Width, unsigned int &AOI_Height) |
Returns the configured AOI size. More... | |
bool | GetBitsPerPixel (unsigned int ChannelIndex, unsigned int &ValidBits, unsigned int &BufferBits) |
Returns the number of bits for each pixel. More... | |
bool | GetBufferSize (unsigned int ChannelIndex, unsigned int &Bytes) |
Returns the number of bytes allocated for each image buffer. More... | |
bool | GetNumberOfInputs (const VIB::CameraLinkIn::MODULE_CONFIGURATION ModuleConfig, unsigned int &NumberOfInputs) |
Returns the number of independent camera channels for the given configuration. More... | |
bool | Reset () |
Resets the device to default settings. More... | |
bool | WaitForImageBuffer (unsigned int ChannelIndex, unsigned int msTimeOut, void **pPtr, bool &IsContentValid) |
Waits for completion of image buffers and transfers ownership to the user. More... | |
bool | WaitForImageBuffer (unsigned int ChannelIndex, unsigned int msTimeOut, void **pPtr, bool &IsContentValid, unsigned long long ×tamp) |
Waits for completion of image buffers and transfers ownership to the user. More... | |
Public Member Functions inherited from VIB::iDevice | |
bool | Close () |
Closes a device More... | |
iDevice (const iDevice &device) | |
The copy constructor makes a copy of the existing device object More... | |
bool | isOpen (bool &state) |
Returns the open state of a device object More... | |
bool | Open (unsigned int Index=0) |
Opens a device More... | |
iDevice & | operator= (const iDevice &device) |
The assignment operator makes a copy of the existing device object More... | |
virtual | ~iDevice () |
Deletes the device object More... | |
The source signals for the Camera Link CC lines, used by ConfigureCC()
Special or additional configuration modes, used by ConfigureCLInput()
The data organization on the Camera Link interface, used by ConfigureCLInput()
Type of Camera Link module configuration ConfigureModule()
Enumerator | |
---|---|
CL_IN_MODULECONFIG_BASE | CL-Base input, one cable for one camera. |
CL_IN_MODULECONFIG_MEDIUM | CL-Medium input, two cables for one camera. |
CL_IN_MODULECONFIG_FULL | CL-Full input, two cables for one camera. |
CL_IN_MODULECONFIG_DECA | CL-Deca input, two cables for one camera. |
CL_IN_MODULECONFIG_AUTO | Automatically determine configuration based on INMODE_TYPE (default) |
VIB::CameraLinkIn::CameraLinkIn | ( | ) |
Default constructor for the device object
The device must be opened with Open() before it can be used.
bool VIB::CameraLinkIn::AbortBufferUsage | ( | const unsigned int | ChannelIndex | ) |
Forces the driver to stop using image buffers.
After return of this function, the user can obtain ownership of the buffers by calling WaitForImageBuffer(). Buffers cannot be added to the acquisition queue again, they can only be freed.
ChannelIndex | Camera index, 0 ... GetNumberOfInputs() |
true
for success, use VIBSystem::GetLastErrorString() for an error descriptionbool VIB::CameraLinkIn::AbortWaitingForDMA | ( | const unsigned int | ChannelIndex | ) |
Forces all waiting threads to return from the WaitForImageBuffer() function call.
WaitForImageBuffer() calls normally return with an error, but they may also return with a buffer or a timeout depending on the timing.
New calls to WaitForImageBuffer() are not allowed until this function returns.
Image acquisition is not affected by this function, the library continues using the buffers in the aquisition queue until AbortBufferUsage() is called.
ChannelIndex | Camera index, 0 ... GetNumberOfInputs() |
true
for success, use VIBSystem::GetLastErrorString() for an error descriptionbool VIB::CameraLinkIn::AddImageBufferForCapturing | ( | const unsigned int | ChannelIndex, |
void * | ptr | ||
) |
Adds an image buffer to the acquisition queue for capturing new camera frames.
After a buffer was added to the queue using this function it is controlled by the library. Its not allowed to access or free this buffer until the buffer is delivered to the user by calling WaitForImageBuffer().
For area scan cameras, the grabber will fill available image buffers in the queue with valid camera frames. If no buffers are available, camera frames will get dropped.
For line scan cameras (see CL_IN_INMODE_FLAGS_IGNORE_FVAL), the grabber will accumulate valid camera lines into available buffers. If no buffers are available, camera lines will get dropped.
There is no rule in which sequence the added buffers are used.
ChannelIndex | Camera index, 0 ... GetNumberOfInputs() |
ptr | Pointer to a valid image buffer, allocated with AllocateImageBuffer() |
true
for success, use VIBSystem::GetLastErrorString() for an error descriptionbool VIB::CameraLinkIn::AllocateImageBuffer | ( | const unsigned int | ChannelIndex, |
void ** | pptr | ||
) |
Allocates a image buffer for capturing.
The allocated buffer size can be obtained with GetBufferSize().
free()
or delete()
. ChannelIndex | Camera index, 0 ... GetNumberOfInputs() |
pptr | Pointer to the new image buffer |
true
for success, use VIBSystem::GetLastErrorString() for an error descriptionbool VIB::CameraLinkIn::ConfigureCC | ( | const unsigned int | ChannelIndex, |
const unsigned int | CCIndex, | ||
const VIB::CameraLinkIn::CC_SOURCE | src, | ||
const bool | Invert | ||
) |
Selects the source for the given CameraLink-CC line.
See Triggering Camera Link cameras for example code.
ChannelIndex | Camera index, 0 ... GetNumberOfInputs() |
CCIndex | Index for the CC-Line [1...4] |
src | The desired source signal |
Invert | Polarity of the output signal |
true
for success, use VIBSystem::GetLastErrorString() for an error descriptionbool VIB::CameraLinkIn::ConfigureCLInput | ( | unsigned int | ChannelIndex, |
VIB::CameraLinkIn::INMODE_TYPE | InType, | ||
unsigned int | InFlags, | ||
unsigned int | AOI_Width, | ||
unsigned int | AOI_Height, | ||
unsigned int | AOI_X = 0 , |
||
unsigned int | AOI_Y = 0 |
||
) |
Initializes a camera channel.
In order to reconfigure a camera channel with this function, the acquisition has to be stopped with AbortBufferUsage and all buffers have to be freed first.
ChannelIndex | Camera index, 0 ... GetNumberOfInputs() |
InType | Camera Link pixel format |
InFlags | Bitwise OR of configuration flags defined in INMODE_FLAGS Use CL_IN_INMODE_FLAGS_DEFAULT for area scan cameras and CL_IN_INMODE_FLAGS_IGNORE_FVAL for line scan cameras |
AOI_Width | AOI width |
AOI_Height | AOI height |
AOI_X | Horizontal start position |
AOI_Y | vertical start position |
true
for success, use VIBSystem::GetLastErrorString() for an error descriptionbool VIB::CameraLinkIn::ConfigureCLInput | ( | unsigned int | ChannelIndex, |
VIB::CameraLinkIn::INMODE_TYPE | InType, | ||
unsigned int | InFlags, | ||
unsigned short | Width, | ||
unsigned short | Height, | ||
unsigned short | AOI_X, | ||
unsigned short | AOI_Y, | ||
unsigned short | AOI_Width, | ||
unsigned short | AOI_Height | ||
) |
Initializes a camera channel.
In order to reconfigure a camera channel with this function, the acquisition has to be stopped with AbortBufferUsage and all buffers have to be freed first.
ChannelIndex | Camera index, 0 ... GetNumberOfInputs() |
InType | Camera Link pixel format |
InFlags | Bitwise OR of configuration flags defined in INMODE_FLAGS Use CL_IN_INMODE_FLAGS_DEFAULT for area scan cameras and CL_IN_INMODE_FLAGS_IGNORE_FVAL for line scan cameras |
Width | The complete camera frame width |
Height | The complete camera frame Height |
AOI_X | Horizontal start position |
AOI_Y | vertical start position |
AOI_Width | AOI width |
AOI_Height | AOI height |
true
for success, use VIBSystem::GetLastErrorString() for an error descriptionbool VIB::CameraLinkIn::ConfigureModule | ( | const VIB::CameraLinkIn::MODULE_CONFIGURATION | ModuleConfig | ) |
Configures the module to the given CL mode.
The default mode is CL_IN_MODULECONFIG_AUTO: the CL configuration is determined by the InType paramter when calling ConfigureCLInput().
ModuleConfig | the new working mode for the whole module |
true
for success, use VIBSystem::GetLastErrorString() for an error descriptionbool VIB::CameraLinkIn::FreeImageBuffer | ( | const unsigned int | ChannelIndex, |
void * | ptr | ||
) |
Frees the specified buffer.
It is only allowed to clean up buffers which are owned by the user. Use AbortBufferUsage() and WaitForImageBuffer() to gain ownership for buffers in the acquisition queue.
ChannelIndex | Camera index, 0 ... GetNumberOfInputs() |
ptr | Pointer to the image buffer |
true
for success, use VIBSystem::GetLastErrorString() for an error descriptionbool VIB::CameraLinkIn::GetAOI | ( | unsigned int | ChannelIndex, |
unsigned int & | AOI_X, | ||
unsigned int & | AOI_Y, | ||
unsigned int & | AOI_Width, | ||
unsigned int & | AOI_Height | ||
) |
Returns the configured AOI size.
The camera channel must be configured with ConfigureCLInput() before calling this function.
ChannelIndex | Camera index, 0 ... GetNumberOfInputs() |
AOI_X | Horizontal AOI start position |
AOI_Y | Vertical AOI start position |
AOI_Width | AOI width |
AOI_Height | AOI height |
true
for success, use VIBSystem::GetLastErrorString() for an error descriptionbool VIB::CameraLinkIn::GetBitsPerPixel | ( | unsigned int | ChannelIndex, |
unsigned int & | ValidBits, | ||
unsigned int & | BufferBits | ||
) |
Returns the number of bits for each pixel.
The camera channel must be configured with ConfigureCLInput() before calling this function.
ChannelIndex | Camera index, 0 ... GetNumberOfInputs() |
ValidBits | Number of usable bits per pixel |
BufferBits | Number of bits per pixel used in the image buffers, including the unused padding bits |
true
for success, use VIBSystem::GetLastErrorString() for an error descriptionbool VIB::CameraLinkIn::GetBufferSize | ( | unsigned int | ChannelIndex, |
unsigned int & | Bytes | ||
) |
Returns the number of bytes allocated for each image buffer.
The camera channel must be configured with ConfigureCLInput() before calling this function.
ChannelIndex | Camera index, 0 ... GetNumberOfInputs() |
Bytes | Number of bytes |
true
for success, use VIBSystem::GetLastErrorString() for an error descriptionbool VIB::CameraLinkIn::GetNumberOfInputs | ( | const VIB::CameraLinkIn::MODULE_CONFIGURATION | ModuleConfig, |
unsigned int & | NumberOfInputs | ||
) |
Returns the number of independent camera channels for the given configuration.
The number depends on hardware, firmware and the specified Camera Link configuration. The returned number can be 0 for not supported, 1 for one channel and 2 for two channels (CL Base only).
ModuleConfig | Specifies the configuration for which the function returns the number of channels |
NumberOfInputs | Returns the number of channels / cameras which can be connected |
true
for success, use VIBSystem::GetLastErrorString() for an error descriptionbool VIB::CameraLinkIn::Reset | ( | ) |
Resets the device to default settings.
Only the CC lines are currently affected when calling this function. All signals are turned off (CL_IN_CC_SRC_OFF).
true
for success, use VIBSystem::GetLastErrorString() for an error descriptionbool VIB::CameraLinkIn::WaitForImageBuffer | ( | unsigned int | ChannelIndex, |
unsigned int | msTimeOut, | ||
void ** | pPtr, | ||
bool & | IsContentValid | ||
) |
Waits for completion of image buffers and transfers ownership to the user.
See overloaded version of WaitForImageBuffer() with the additional timestamp parameter for a detailed description.
bool VIB::CameraLinkIn::WaitForImageBuffer | ( | unsigned int | ChannelIndex, |
unsigned int | msTimeOut, | ||
void ** | pPtr, | ||
bool & | IsContentValid, | ||
unsigned long long & | timestamp | ||
) |
Waits for completion of image buffers and transfers ownership to the user.
Multiple threads can call this function simultaneously. The first caller returns first with the next completed buffer.
After successful return of the function, one of three events have occured:
NULL
):After a valid buffer was returned, it can be released with FreeImageBuffer() or added to the acquisition queue again with WaitForImageBuffer().
This function is also used to obtain buffers after AbortBufferUsage() was called.
ChannelIndex | Camera index, 0 ... GetNumberOfInputs() |
msTimeOut | TimeOut in milliseconds, 0 ... INFINITE |
pPtr | Double pointer for storing the new image buffer or NULL |
IsContentValid | If the returned image buffer in pPtr is valid, this flag indicates if the buffer contents are valid (acquisition was successful) |
timestamp | If the returned image buffer in pPtr is valid, the timestamp value contains the point in time of the image transfer completion within the driver. The timestamp value is stored in micro-seconds and is based on the following clocks: Windows: performance counter (QueryPerformanceCounter()), requires driver ≥ v1.3.2.0 Linux: CLOCK_MONOTONIC, requires driver ≥ v1.2.0.0 The value will be zero if the driver doesn't support timestamps. |
true
for success, use VIBSystem::GetLastErrorString() for an error description