IDS peak comfortC v1.14.2
Loading...
Searching...
No Matches
Main page

Introduction

IDS peak comfortC provides access to the complete set of features that is required to operate IDS cameras.
The main objective of IDS peak comfortC is to encapsulate the underlying GenICam standard technology and to free the user from the requirement to have a deeper understanding of the GenICam standard and its abstract paradigms.

Technically IDS peak comfortC encapsulates the IDS peak genericSDK as its Backend.

Prerequisites

The library requires the use of C99 for the client application.

Qt of at least version 5.7 and C++14 is required for the GUI samples.
Qt must be installed on the system if you want to compile the sample code by yourself.
For Linux Qt must also be in installed to run the GUI samples.

How to use

In order to use IDS peak comfortC you need to include the interface header file ids_peak_comfort_c.h and link your application with the ids_peak_comfort_c library.

In order to run an application the shared libraries must be found by the system.
For Windows copy the deployed shared libraries (dll) into the folder with the applications executable.
For Linux add the path to the deployed shared libraries (so) to LD_LIBRARY_PATH.

Terms

This section defines several terms that are used throughout the IDS peak comfortC library.

Library

The term library is used to refer to the IDS peak comfortC library and its implementation.

Backend

The term backend is used to refer to the backend of the IDS peak comfortC library which is the IDS peak genericSDK.
IDS peak genericSDK is built by IDS peak genericAPI and the IDS peak IPL.

Convenience Interface

All feature-related functions of IDS peak comfortC together are referred to as the convenience interface of the library.

The Generic Feature Access (GFA) functions do not belong to the convenience interface.

Application

The term application is used to refer to the user application, i.e. to the IDS peak comfortC client program.

Access Status

The access status of a feature or a camera indicates the current availability of the feature or the camera.

A feature or camera can reside permanently or temporarily in a certain access status. For example:

  • A feature may be permanently 'not supported' for a camera because the camera does not implement it.
  • A feature may be temporarily 'read only' depending on the status of another feature, e.g. acquisition running.
  • A camera may be temporarily 'not accessible' while it is opened in a different application.
  • An ethernet camera may be temporarily 'not accessible' because its IP configuration is incompatible.

The current access status of a feature or camera can be queried via specific functions.

See also
Access Status Query

Enabled Status

The enabled status of a feature indicates whether the feature is currently enabled or disabled.

The enabled status can take the boolean values PEAK_TRUE for enabled and PEAK_FALSE for disabled.

The current enabled status of a feature can be queried via specific functions.

See also
Enabled Status Query

Frame

A frame is an entity of bulk data which was acquired from a camera.
It combines the memory Buffer to which the bulk data was received and the meta information on the properties of the data.

Typically, a frame represents an acquired image.
But it can also represent other types of bulk data received from a camera. The type of data that a frame represents depends on the camera settings.

Buffer

A buffer is an entity in the computer memory which can store a certain amount of data.

A buffer is defined by its memory address and the size of the memory in bytes.
In addition a buffer can store a user defined pointer for context purposes.

Buffer Underrun

A buffer underrun is counted when a frame transmission arrives but there is no image buffer available to store it to.

This is the case when all image buffers are locked for the reception of incoming image data. The library automatically locks an image buffer after it was filled with image data. The buffer is then not available to store newly incoming image data until it has been delivered to the application via peak_Acquisition_WaitForFrame and released via peak_Frame_Release. So, the application is responsible for unlocking the buffer via peak_Frame_Release.

In order to avoid buffer underruns in an application

  • minimize the time a buffer is locked. If the time that a buffer is locked regularly exceeds the frame time (i.e. the reciprocal frame rate) you will inevitably get buffer underruns.
  • increase the number of image buffers the implementation can use. If the time that a buffer is locked occasionally exceeds the frame time increasing the number of announced buffers can avoid buffer underruns. In Manual Buffer Preparation mode the number of buffers is defined by the number of calls to peak_Acquisition_Buffer_Announce.

Dropped Frame

A dropped frame is counted when the frame id of a received frame jumps forward in respect to the last received frame.

This is the case when the camera is not able to transmit or to buffer an acquired image.
This situation typically arises when the cameras' acquisition rate is higher than the rate of frames that it can transmit via the bus.

In order to avoid dropped frames in an application

  • choose an acquisition frame rate that does not overstrain the available bus bandwidth.
  • minimize the occurrence of incomplete frames, see Incomplete Frame.

Incomplete Frame

An incomplete frame is counted when a frame could not be completely transmitted from the camera to the host.

A frame is usually transmitted in a number of transmission units, so-called packets. If at least one of the packets could not be correctly transmitted for a frame, this frame is referred to as incomplete.

This is a typical issue for Ethernet connections as the underlying UDP transport protocol is not reliable, i.e. there is no guarantee of delivery, ordering, or duplicate protection of the transmitted data packets.
Even if the transport layer implements recovery actions for this issue it may not be able to fully prevent packet loss.

In order to minimize incompletes in an application

  • make sure the total acquired bus bandwidth does not exceed the available bus bandwidth in any segment of the connection.
  • take care that the cabling is of sufficient quality and protected from environmental electromagnetic influences.

Core Principles

This section describes some basic principles and programming paradigms of the library.

The application programmer can rely on the library following these principles' throughput the whole interface.

Strong Exception Safety

Wherever possible the library guarantees strong exception safety.

Strong exception safety is also known as commit or rollback semantics.
The point of strong exception safety is that a failed operation has no side effects. This means that the system status after a failed function is the same as it was before the function call.

Please note that it might not be possible to achieve this goal for every specific situation.

Function Return Values

In principle all functions of the library return a status code of type peak_status.

If a function succeeds it will return PEAK_STATUS_SUCCESS. The macro PEAK_SUCCESS can be used to test a returned status code for indication of success.
If a function fails it will return an error code. The macro PEAK_ERROR can be used to test a returned status code for failure indication.

It is strongly recommended checking the return value of every library function call for an error indication.

In addition, there is a third class of status codes which indicate a warning level status. The macro PEAK_WARNING can be used to test a returned status code for indication of a warning.
An example for a warning level status code is PEAK_STATUS_VALUE_ADJUSTED which indicates that the function was not able to apply the exact desired value to a feature and that the value has been adjusted to for example the nearest valid neighbor.

If a function returns an error code, i.e. PEAK_ERROR returns PEAK_TRUE on the status code, the details on the error can be queried via peak_Library_GetLastError. See also Last Error Handling.

Note
There are certain groups of library functions which deviate from the principle that all functions return a peak_status code. For an explanation of these function groups see

Last Error Handling

The library stores the last error separately for each application thread.

A descriptive message on the last error that occurred in the current thread context can be queried via peak_Library_GetLastError. This message describes the error and its cause in as much detail as possible.

The last error is not cleared after peak_Library_GetLastError has been called.
It is therefore strongly advised to evaluate the last error only in the immediate context of a failed library function call, i.e. a library function indicating an error by a peak_status error code or by PEAK_ACCESS_INVALID.

A code example on how to query the last error is given in the section Two Staged Data Query.

Note
In case peak_Library_GetLastError itself fails it will return the appropriate error code, but it will not store the error internally so that succeeding calls to peak_Library_GetLastError will still be able to report the original error.

Two Staged Data Query

Several library functions provide data of dynamic size in a memory buffer that is to be provided by the application. As the size of the data depends on the required memory buffer size can not be known a priori.

To access such data the application should implement the following procedure:

  • Stage One: Query the required size of the memory buffer by calling the function with the buffer parameter set to NULL.
  • Stage Two: Receive the data by calling the function with a buffer that was allocated to the size that Stage one returned.

The following code demonstrates this procedure by the example of peak_Library_GetLastError.

char* errMsg = NULL;
size_t errMsgSize = 0;
// For peak_Library_GetLastError the second parameter is the buffer parameter.
// For Stage One, i.e. the size query, we pass a buffer parameter of NULL.
peak_status status = peak_Library_GetLastError(&errCode, NULL, &errMsgSize);
if (PEAK_SUCCESS(status) == PEAK_TRUE)
{
// The size of the last error message was successfully stored in errMsgSize.
// This is the size of memory we have to allocate to receive the message.
errMsg = (char*)malloc(errMsgSize);
memset(errMsg, 0, errMsgSize);
// For Stage Two, i.e. the data query, we pass the allocated memory as the buffer parameter.
status = peak_Library_GetLastError(&errCode, errMsg, &errMsgSize);
if (PEAK_SUCCESS(status) == PEAK_TRUE)
{
// The last error message was successfully stored in errMsg.
}
}
peak_status peak_Library_GetLastError(peak_status *lastErrorCode, char *lastErrorMessage, size_t *lastErrorMessageSize)
Query the last error.
#define PEAK_TRUE
peak Boolean value for 'true' or 'yes'
Definition ids_peak_comfort_c.h:910
peak_status
peak Status codes
Definition ids_peak_comfort_c.h:1077
#define PEAK_SUCCESS(status)
Check for the status code to indicate success.
Definition ids_peak_comfort_c.h:1182
@ PEAK_STATUS_SUCCESS
Success.
Definition ids_peak_comfort_c.h:1079

The following code demonstrates this procedure by the example of peak_CameraList_Get.

peak_camera_descriptor* cameraList = NULL;
size_t cameraCount = 0;
// For peak_CameraList_Get the first parameter is the buffer parameter.
// For Stage One, i.e. the size query, we pass a buffer parameter of NULL.
peak_status status = peak_CameraList_Get(NULL, &cameraCount);
if (PEAK_SUCCESS(status) == PEAK_TRUE)
{
// The size of the camera list was successfully stored in cameraCount.
// We need to allocate a memory buffer that can store this number of camera descriptors.
cameraList = (peak_camera_descriptor*)malloc(cameraCount * sizeof(peak_camera_descriptor));
memset(cameraList, 0, cameraCount * sizeof(peak_camera_descriptor));
// For Stage Two, i.e. the data query, we pass the allocated memory as the buffer parameter.
status = peak_CameraList_Get(cameraList, &cameraCount);
if (PEAK_SUCCESS(status) == PEAK_TRUE)
{
// The camera list was successfully stored in cameraList.
}
}
peak_status peak_CameraList_Get(peak_camera_descriptor *cameraList, size_t *cameraCount)
Query the current camera list.
peak Camera descriptor
Definition ids_peak_comfort_c.h:1545
Note
The list of connected camera may change in the time between Stage One and Stage Two if a call to peak_CameraList_Update is executed in this time, for example in a different thread.
If the implementation detects more cameras in Stage Two than it has detected in Stage One the function will return with PEAK_STATUS_BUFFER_TOO_SMALL.
If the implementation detects fewer cameras in Stage Two than it has detected in Stage One the function will fill the buffer with the camera descriptors of the connected cameras and return the number of used list slots in cameraCount.

The following code demonstrates this procedure by the example of peak_PixelFormat_GetList.

peak_pixel_format* pixelFormatList = NULL;
size_t pixelFormatCount = 0;
// For peak_PixelFormat_GetList the second parameter is the buffer parameter.
// For Stage One, i.e. the size query, we pass a buffer parameter of NULL.
peak_status status = peak_PixelFormat_GetList(hCam, NULL, &pixelFormatCount);
if (PEAK_SUCCESS(status) == PEAK_TRUE)
{
// The size of the pixel format list was successfully stored in pixelFormatCount.
// We need to allocate a memory buffer that can store this number of pixel formats.
pixelFormatList = (peak_pixel_format*)malloc(pixelFormatCount * sizeof(peak_pixel_format));
memset(pixelFormatList, 0, pixelFormatCount * sizeof(peak_pixel_format));
// For Stage Two, i.e. the data query, we pass the allocated memory as the buffer parameter.
status = peak_PixelFormat_GetList(hCam, pixelFormatList, &pixelFormatCount);
if (PEAK_SUCCESS(status) == PEAK_TRUE)
{
// The pixel format list message was successfully stored in pixelFormatList.
}
}
peak_status peak_PixelFormat_GetList(peak_camera_handle hCam, peak_pixel_format *pixelFormatList, size_t *pixelFormatCount)
Get the list of currently selectable pixel formats.
peak_pixel_format
peak Pixel format
Definition ids_peak_comfort_c.h:3423
Note
The list of selectable pixel formats may change in the time between Stage One and Stage Two if the camera configuration or the camera status changes in this time, for example in a different thread.
If there are more pixel formats selectable in Stage Two than in Stage One the function will return with PEAK_STATUS_BUFFER_TOO_SMALL.
If there are less pixel formats selectable in Stage Two than in Stage One the function will fill the buffer with the then selectable pixel formats and return the number of used list slots in cameraCount.
This behaviour is the same for all features which provide the list of valid values by this principle.
If a function which implements this principle fills data into the buffer it will return the size it filled in the size parameter.

Alternative One Stage approach

In order to spare the size query Stage you may want to pass a buffer that is large enough to store the maximum expected size of data.

For example, you can shortcut the size query for the camera list query if you provide a buffer that is capable of storing the camera descriptors of all cameras that could possibly be connected.

Another example is the last error query. The library will not provide an error message whose length exceeds 1 kB of characters.
With this assumption the example on peak_Library_GetLastError shortens to the following code.

// A memory buffer for 1024 characters should be sufficient to receive all possible error messages.
char errMsg[1024];
size_t errMsgSize = sizeof(errMsg);
memset(errMsg, 0, errMsgSize);
peak_status status = peak_Library_GetLastError(&errCode, errMsg, &errMsgSize);
if (PEAK_SUCCESS(status) == PEAK_TRUE)
{
// The number of filled characters is provided in errMsgSize.
// The string provided in errMsg is zero-terminated.
}
else if (status == PEAK_STATUS_BUFFER_TOO_SMALL)
{
// Oops. The error message exceeds the size of 1024 characters.
}
@ PEAK_STATUS_BUFFER_TOO_SMALL
The buffer is too small to take the complete data.
Definition ids_peak_comfort_c.h:1140
Note
If the data does not fit into the provided buffer the functions will return PEAK_STATUS_BUFFER_TOO_SMALL.

Camera ID Query

The library provides specific functions for the translation of a certain camera property into the related camera id.

In general all library functions that are related to a certain camera instance require a camera handle (peak_camera_handle) as a parameter to identify the individual camera which is addressed by the function call.
In order to receive the camera handle that allows to use these functions the camera must have been opened before.

However, there are also library functions which can be used on a closed camera.
These functions take a camera id (peak_camera_id) instead of the camera handle.

In order to find the camera id of the camera with a certain property, for example a certain serial number, one would walk the camera descriptors in the camera list and look for the desired camera.

The library provides a number of functions save the application from this procedure.

These functions have in common that they deviate from the generic rule that every library function returns a status code.
This allows a direct simple approach to address a camera with a certain property in the functions that require a camera id as identifier.
The following code demonstrates this by the example of opening a camera with a certain serial number.

const char serialNumber[] = "123456789";
const peak_camera_id cameraID = peak_Camera_ID_FromSerialNumber(serialNumber);
{
// Got the camera id for the camera with the desired serial number.
// Open the camera.
if (PEAK_ERROR(peak_Camera_Open(cameraID, &hCam)) == PEAK_TRUE)
{
// Opening the camera failed.
// Query the error details.
char errMsg[1024];
size_t errMsgSize = sizeof(errMsg);
memset(errMsg, 0, errMsgSize);
if (PEAK_SUCCESS(peak_Library_GetLastError(&errCode, errMsg, &errMsgSize)) == PEAK_TRUE)
{
// errCode: Error code for the failed call to peak_Camera_Open
// errMsg: Error description for the failed call to peak_Camera_Open
}
}
}
else
{
// The camera id query failed.
// Query the error details.
char errMsg[1024];
size_t errMsgSize = sizeof(errMsg);
memset(errMsg, 0, errMsgSize);
if (PEAK_SUCCESS(peak_Library_GetLastError(&errCode, errMsg, &errMsgSize)) == PEAK_TRUE)
{
// errCode: Error code for the failed call to peak_Camera_ID_FromSerialNumber
// errMsg: Error description for the failed call to peak_Camera_ID_FromSerialNumber
}
}
uint64_t peak_camera_id
peak Camera ID
Definition ids_peak_comfort_c.h:1524
struct peak_camera * peak_camera_handle
peak Camera handle
Definition ids_peak_comfort_c.h:1509
peak_camera_id peak_Camera_ID_FromSerialNumber(const char *serialNumber)
Query the camera id by the serial number.
#define PEAK_INVALID_CAMERA_ID
peak Invalid camera ID value
Definition ids_peak_comfort_c.h:1532
peak_status peak_Camera_Open(peak_camera_id cameraID, peak_camera_handle *hCam)
Open the camera by the Camera id.
#define PEAK_INVALID_HANDLE
peak Invalid handle value
Definition ids_peak_comfort_c.h:878
#define PEAK_ERROR(status)
Check for the status code to indicate an error.
Definition ids_peak_comfort_c.h:1208

An even simpler approach is demonstrated by this example:

const char serialNumber[] = "123456789";
{
// Opening the camera failed.
// Query the error details.
char errMsg[1024];
size_t errMsgSize = sizeof(errMsg);
memset(errMsg, 0, errMsgSize);
if (PEAK_SUCCESS(peak_Library_GetLastError(&errCode, errMsg, &errMsgSize)) == PEAK_TRUE)
{
// errCode: Error code for the failed call to peak_Camera_Open
// errMsg: Error description for the failed call to peak_Camera_Open
}
}

Note that for the latter example it is not possible to query the error details for the actual problem.
Instead the last error query will tell that peak_Camera_Open was called with an invalid camera id.
This is because the last error information that was set by peak_Camera_ID_FromSerialNumber is overwritten with the last error information of the call to peak_Camera_Open which is proceeded after the call to peak_Camera_ID_FromSerialNumber.

On the specific return type and on error indication for camera id queries

The majority of the library functions return a peak_status code.
Besides these functions there is an additional group of functions which return a peak_camera_id.

The decision to have these functions report the camera id as a return value rather than as a function parameter was made for the reason of a simpler and a more compact and efficient usage in the application code.
By this an application can directly address a camera with a certain property value in the library functions that require a camera id as a camera identifier.

However, such a function can easily fail. For example if there is no camera with the specified property value.

If so, the function will return PEAK_INVALID_CAMERA_ID as an unspecific error indication.
The details on the error can then be queried via peak_Library_GetLastError which provides the error information as a peak_status code and a descriptive message on the error.
See the example above.

Access Status Query

For a description of the term Access Status see Access Status.

The library provides specific functions for the query of the current access status of a certain feature or a camera.

These functions have in common that they deviate from the generic rule that every library function returns a status code.
This allows a direct simple switching on the access status, as the following example demonstrates:

const peak_camera_id camID = 1;
switch (peak_Camera_GetAccessStatusByCameraID(camID))
{
// The camera is available for use.
peak_status status = peak_Camera_Open(camID, &hCam);
...
break;
// The camera is currently not available for use.
// Maybe it is opened in a different application
// or it its configuration is not compatible to the system
// (for example the cameras IP address is not properly configured).
...
break;
// The access status query failed.
// Query the error details.
char errMsg[1024];
size_t errMsgSize = sizeof(errMsg);
memset(errMsg, 0, errMsgSize);
const peak_status status = peak_Library_GetLastError(&errCode, errMsg, &errMsgSize);
if (PEAK_SUCCESS(status) == PEAK_TRUE)
{
// errCode: Error code for the failed call to peak_Camera_GetAccessStatusByCameraID
// errMsg: Error description for the failed call to peak_Camera_GetAccessStatusByCameraID
}
break;
}
@ PEAK_ACCESS_INVALID
Invalid access status code.
Definition ids_peak_comfort_c.h:1227
@ PEAK_ACCESS_NONE
No access.
Definition ids_peak_comfort_c.h:1241
@ PEAK_ACCESS_READWRITE
Read write access.
Definition ids_peak_comfort_c.h:1266

On the specific return type and on error indication for access status queries

The majority of the library functions return a peak_status code.
Besides these functions there is an additional group of functions which return a peak_access_status code.

The decision to have these functions report the access status as a return value rather than as a function parameter was made for the reason of a simpler and a more compact and efficient usage in the application code.
By this an application can directly switch on the access status of a functional module or a camera.

Moreover, the functions that implement the Access Status Query principle will rarely fail, as long as the library is initialized.

Nonetheless, in theory such a function can fail. For example if the library is not initialized.

If so, the function will return PEAK_ACCESS_INVALID as an unspecific error indication.
The details on the error can then be queried via peak_Library_GetLastError which provides the error information as a peak_status code and a descriptive message on the error.
See the example above.

Simplified Evaluation of an Access Status

In practice the access status will mostly be queried in order to determine whether a feature can be written to or read from.

The library offers the macros PEAK_IS_WRITEABLE and PEAK_IS_READABLE to allow phrasing these query in an even more compact way:

{
// The exposure time feature is writeable.
peak_ExposureTime_Set(hCam, 100.0);
}
peak_status peak_ExposureTime_Set(peak_camera_handle hCam, double exposureTime_us)
Set the exposure time.
peak_access_status peak_ExposureTime_GetAccessStatus(peak_camera_handle hCam)
Query the exposure time access status.
#define PEAK_IS_WRITEABLE(accessStatus)
Check for the access status code to indicate write access to be possible.
Definition ids_peak_comfort_c.h:1284

But: Be aware that these macros will return PEAK_FALSE not only if the feature is not writeable/readable. They will return PEAK_FALSE also if the access status query failed. For example because the passed handle is invalid.
So, for to be sure that the access status query did not fail on the macro returning PEAK_FALSE, you would have to further investigate the access status on PEAK_FALSE:

if (PEAK_IS_WRITEABLE(accessStatus) == PEAK_TRUE)
{
// The exposure time feature is readable.
double exposureTime;
peak_ExposureTime_Get(hCam, &exposureTime);
}
else
{
// The exposure time feature is not readable or the access status query failed.
if (accessStatus == PEAK_ACCESS_INVALID)
{
// Access status query failed
}
}
peak_status peak_ExposureTime_Get(peak_camera_handle hCam, double *exposureTime_us)
Get the exposure time.
peak_access_status
peak Access status codes
Definition ids_peak_comfort_c.h:1219

Boolean Status Queries

The library provides specific functions for the query of a boolean status.

These functions have in common that they deviate from the generic rule that every library function returns a status code.
This allows a direct simple switching on the boolean status, as the following examples in the following sections demonstrate.

The downside of this approach is that it is not possible for these functions to return an error. See the section On the specific return type and on error indication for boolean status queries on this topic.

Enabled Status Query

For a description of the term Enabled Status see Enabled Status.

The library provides specific functions for the query of the current enabled status of a certain feature.

These functions have in common that they deviate from the generic rule that every library function returns a status code.
This allows a direct simple switching on the enabled status, as the following example demonstrates:

if (peak_Trigger_IsEnabled(hTriggerConfig) == PEAK_TRUE)
{
// The trigger configuration is currently enabled.
}
else
{
// The trigger configuration is currently disabled
// or the query failed.
}
peak_bool peak_Trigger_IsEnabled(peak_camera_handle hCam)
Get the enabled status of the trigger.

The downside of this approach is that it is not possible for these functions to return an error. See the section On the specific return type and on error indication for boolean status queries on this topic.

Valid Values Organization Query

For a description of the libraries concept on the query for a features valid values see Feature Valid Values Query.

The library provides specific functions for the query of the organization of the valid values for a certain feature.

These functions have in common that they deviate from the generic rule that every library function returns a status code.
This allows a direct simple switching on the indication whether the features valid values are organized as a range or as a list, as the following example demonstrates:

{
// The pixel clock features valid values are organized as a range.
status = peak_PixelClock_GetRange(hCam, &min, &max, &inc);
}
else
{
// The pixel clock features valid values are organized as a list.
status = peak_PixelClock_GetList(hCam, &list, &count);
}
peak_bool peak_PixelClock_HasRange(peak_camera_handle hCam)
Check whether the valid values for the pixel clock feature are organized as a range.
peak_status peak_PixelClock_GetRange(peak_camera_handle hCam, double *minPixelClock_MHz, double *maxPixelClock_MHz, double *incPixelClock_MHz)
Get the current range of valid pixel clock values.
peak_status peak_PixelClock_GetList(peak_camera_handle hCam, double *pixelClockList, size_t *pixelClockCount)
Get the list of currently selectable pixel clock values.

The downside of this approach is that it is not possible for these functions to return an error. See the section On the specific return type and on error indication for boolean status queries on this topic.

On the specific return type and on error indication for boolean status queries

The majority of the library functions return a peak_status code.
Besides these functions there is an additional group of functions which return a peak_bool value.

The decision to have these functions report the boolean status as a return value rather than as a function parameter was made for the reason of a simpler and a more compact and efficient usage in the application code.
By this an application can directly switch on the boolean status of a functional module.

Moreover, the functions that implement the Boolean Status Query principle will rarely fail, as long as the library is initialized.

Nonetheless, in theory such a function can fail. For example if the library is not initialized or if it is passed invalid arguments.

If so, the function will return PEAK_FALSE.
As the boolean type does not offer a value beyond true and false it is not possible to indicate failure of the enabled status query.

A failure of the enabled status query is treated just like the feature being disabled.
It is not treated as an error and the library does not store last error information on this.

Functional Concepts

This section provides explanations on the basic functioning of IDS peak comfortC.

Buffer Preparation

In order to receive acquired images from the camera and provide the data to the application the library must be provided with memory buffers to which the incoming image data can be stored.
For an efficient data transfer these buffers must be sufficient in size and number.

A buffer is sufficient in size if it can store the complete image data that results from the feature settings.

The number of buffers is sufficient if all acquired images can be captured by the library and provided to the application.
This is enabled if the library at any time has a buffer available to store incoming image data. In other words there must always be at least one buffer that is not locked for processing by the application.

The library provides two options for the preparation of the image buffers.
The Automatic Buffer Preparation mode is recommended as long as the application does not need to predetermine the memory addresses of the buffers.
If the application needs to use buffers at well-defined memory addresses it must use the Manual Buffer Preparation mode.

Automatic Buffer Preparation

In this mode the library takes care for the preparation of the buffers.

The automatic buffer preparation mode is active by default. The application can switch to the Manual Buffer Preparation mode by using peak_Acquisition_Buffer_Announce to provide self defined buffers.

The library will allocate a sufficient number of sufficiently sized buffers to store the acquired images.
The preparation of the buffers is done in the context of an acquisition start. The size and the number of the buffers that the library allocates depend on the feature settings that apply at the time peak_Acquisition_Start is called.

The following example demonstrates the way to a first image in automatic buffer preparation mode.
The error handling is left out for the reason of example clarity.

peak_buffer buffer = { NULL, 0, NULL };
peak_Frame_Buffer_Get(hFrame, &buffer);
// The memory address where the image data starts is buffer.memoryAddress.
peak_Frame_Release(hCam, hFrame);
peak_status peak_Acquisition_WaitForFrame(peak_camera_handle hCam, uint32_t timeout_ms, peak_frame_handle *hFrame)
Wait for an acquired frame.
peak_status peak_Acquisition_Start(peak_camera_handle hCam, uint32_t numberOfFrames)
Start an acquisition.
peak_status peak_CameraList_Update(size_t *cameraCount)
Update the camera list.
peak_status peak_Camera_Close(peak_camera_handle hCam)
Close the camera.
peak_status peak_Camera_OpenFirstAvailable(peak_camera_handle *hCam)
Open the first available camera.
peak_status peak_Frame_Buffer_Get(peak_frame_handle hFrame, peak_buffer *buffer)
Query the buffer of a frame.
peak_status peak_Frame_Release(peak_camera_handle hCam, peak_frame_handle hFrame)
Release a frame.
struct peak_frame * peak_frame_handle
peak Frame handle
Definition ids_peak_comfort_c.h:2470
peak_status peak_Library_Init()
Init the IDS peak comfortC library.
peak_status peak_Library_Exit()
Exit the IDS peak comfortC library.
#define PEAK_INFINITE
peak Infinite value
Definition ids_peak_comfort_c.h:892
peak Buffer descriptor
Definition ids_peak_comfort_c.h:929

Manual Buffer Preparation

In this mode the application is responsible for the preparation of the buffers.

The application must allocate a sufficient number of sufficiently sized buffers to store the acquired images.
Then the application must announce the allocated buffers to the library. The preparation of the buffers must be done before an acquisition is started.
The library checks for the announced buffers to be sufficient in the context of an acquisition start. If the buffers are not sufficient peak_Acquisition_Start will fail.

The minimum number of buffers that is required by the library can be queried via peak_Acquisition_Buffer_GetRequiredCount. The minimum size of the individual buffers depends on the feature settings and can be queried via peak_Acquisition_Buffer_GetRequiredSize.

In manual buffer preparation mode the application is responsible for the allocated buffer memory. I.e. the application must allocate the memory, and free it when the buffers are not used any longer.
The application must make sure that the memory is valid as long as the buffer is announced to the library.

The following example demonstrates the way to a first image in manual buffer preparation mode.
The error handling is left out for the reason of example clarity.

size_t requiredBufferCount = 0;
size_t requiredBufferSize = 0;
uint8_t** myBuffers = NULL;
peak_buffer buffer = { NULL, 0, NULL };
// apply all desired feature settings before asking for the required buffer size
// query the required buffer count and size
peak_Acquisition_Buffer_GetRequiredCount(hCam, &requiredBufferCount);
peak_Acquisition_Buffer_GetRequiredSize(hCam, &requiredBufferSize);
// allocate an array for the buffers
// we must remember the buffer addresses as we have to revoke and free the buffers when we are finished
myBuffers = (uint8_t**)malloc(requiredBufferCount * sizeof(uint8_t*));
memset(myBuffers, 0, requiredBufferCount * sizeof(uint8_t*));
// allocate and announce the individual buffers
// note that we enter the manual buffer preparation mode with the first call to peak_Acquisition_Buffer_Announce
for (size_t i = 0; i < requiredBufferCount; i++)
{
myBuffers[i] = (uint8_t*)malloc(requiredBufferSize);
peak_Acquisition_Buffer_Announce(hCam, myBuffers[i], requiredBufferSize, NULL);
}
// for the example we acquire only one image
// note that the number of buffers we have to announce nevertheless is requiredBufferCount
peak_Frame_Buffer_Get(hFrame, &buffer);
// The memory address where the image data starts is buffer.memoryAddress.
// It is one of the addresses that we announced.
peak_Frame_Release(hCam, hFrame);
// now that we are done with the acquisition we need to revoke the buffers and free the associated memory
// note that we enter the automatic buffer preparation mode with the first call to peak_Acquisition_Buffer_Announce
for (size_t i = 0; i < requiredBufferCount; i++)
{
peak_Acquisition_Buffer_Revoke(hCam, myBuffers[i]);
free(myBuffers[i]);
}
peak_status peak_Acquisition_Buffer_Revoke(peak_camera_handle hCam, uint8_t *memoryAddress)
Revoke an image buffer.
peak_status peak_Acquisition_Buffer_GetRequiredCount(peak_camera_handle hCam, size_t *requiredBufferCount)
Query the required image buffer count.
peak_status peak_Acquisition_Buffer_Announce(peak_camera_handle hCam, uint8_t *memoryAddress, size_t memorySize, void *userContext)
Announce an image buffer.
peak_status peak_Acquisition_Buffer_GetRequiredSize(peak_camera_handle hCam, size_t *requiredBufferSize)
Query the required image buffer size.

Feature Valid Values Query

Most of the library and camera features require a setting to be within a certain set of valid values.

The definition of the set of valid values can be of one of two types:

  • a range of values with a minimum value, a maximum value, and a value increment or step width
  • a list of discrete values

It depends on the specific feature whether its valid values are organized as a range or as a list.
For those features with a range of valid values the library provides a function which is named according to the following pattern:

peak_<FeatureName>_GetRange()

For those features with a list of valid values the library provides a function which is named according to the following pattern:

peak_<FeatureName>_GetList()

Moreover, for individual features it depends on the specific camera model whether the valid values for a feature are organized as a range or as a list.
For these features the library provides both of the above-mentioned functions and an addition function which indicates which one to use. This function follows this pattern:

peak_<FeatureName>_HasRange()

The following code demonstrates how to query the valid values using the pixel clock feature as an example.

// The organization of the valid values for the pixel clock feature depends on the specific camera.
// So, first we have to decide whether to query a range or a list.
{
// The valid values are organized as a range.
double minPixelClock_MHz = .0;
double maxPixelClock_MHz = .0;
double incPixelClock_MHz = .0;
peak_status status = peak_PixelClock_GetRange(hCam, &minPixelClock_MHz, &maxPixelClock_MHz, &incPixelClock_MHz);
if (PEAK_SUCCESS(status))
{
// A valid value for the pixel clock is between minPixelClock_MHz and maxPixelClock_MHz
// with an increment of incPixelClock_MHz.
}
}
else
{
// The valid values are organized as a list.
size_t pixelClockCount = 0;
peak_status status = peak_PixelClock_GetList(hCam, NULL, &pixelClockCount);
if (PEAK_SUCCESS(status) == PEAK_TRUE)
{
double* pixelClockList = (double*)malloc(pixelClockCount * sizeof(double));
memset(pixelClockList, 0, pixelClockCount * sizeof(double));
status = peak_PixelClock_GetList(hCam, pixelClockList, &pixelClockCount);
if (PEAK_SUCCESS(status) == PEAK_TRUE)
{
// A valid value for the pixel clock is one out pixelClockList.
}
}
}

Generic Feature Access (GFA)

The objective of IDS peak comfortC is to encapsulate the underlying GenICam interface so, that the user does not need to have a deep knowledge of the GenICam standard and its concepts.
This is realized by the libraries Convenience Interface where the functions have a clear naming, typing and behaviour.

Nonetheless, the library provides functions which enable the direct access to the systems feature nodes, i.e. to the nodemap of a GenTL module or to the nodemap of the remote device.
This is realized by the libraries generic feature access (GFA) interface where the functions have a more abstract naming, typing and behaviour.

This generic feature access functions can be used to accomplish tasks which are not (yet) available via the libraries convenience interface.

The GFA functions address single feature nodes of the addressed module and apply parameters on a low-level, atomic basis, whereas the convenience functions typically implement a compound functionality.
For example setting the pixel clock to a certain value via the convenience interface is about calling peak_PixelClock_Set, whereas setting the pixel clock via the GFA interface requires to first set a so-called selector node ("DeviceClockSelector") to a certain value and then writing the desired pixel clock value to the node with the name "DeviceClockFrequency".
Actually, the implementation of the convenience functions internally also operates on the atomic nodes to achieve the desired effect on the configuration.
This raises the problem that an unsynchronized concurrent write access via the GFA interface may interfere with the implementation of a convenience interface function.
In the pixel clock example above an unfortunate thread context switch could lead to a GFA access changing the DeviceClockSelector node just before the convenience implementation was able to write the desired pixel clock value to the DeviceClockFrequency node.
In order to prevent the system from such situations and to synchronize the use of the GFA interface with the procedures of the convenience interface the library provides a specific mode. All write accesses via the GFA interface are possible only in this 'GFA write access mode'.
So, in order to issue a write access via the GFA interface the GFA write access mode must be enabled by the application.
The GFA write access mode takes effect on a per-camera basis.
The following rules apply in respect to the GFA write access mode:

  • While the GFA write access mode is enabled all calls to the camera related convenience interface functions are rejected (PEAK_ACCESS_GFA_LOCK).
  • While the GFA write access mode is disabled all calls to GFA write functions are rejected.
  • The GFA write access mode can be enabled only if there is no running call to a convenience interface function.
Note
The name of a feature in the convenience interface is not necessarily the same name as the corresponding node name as defined by the GenICam Standard Feature Naming Convention or the GenTL Standard Feature Naming Convention.