![]() |
IDS peak comfortC
v1.1.0
|
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.
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.
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.
This section defines several terms that are used throughout the IDS peak comfortC library.
The term library is used to refer to I the IDS peak comfortC library and its implementation.
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 API and the IDS peak IPL.
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.
The term application is used to refer to the user application, i.e. to the IDS peak comfortC client program.
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:
The current access status of a feature or camera can be queried via specific functions.
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.
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.
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.
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 then is 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
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
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
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.
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 may not be possible to achieve this goal for every specific situation.
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.
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.
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:
The following code demonstrates this procedure by the example of peak_Library_GetLastError.
peak_status errCode = PEAK_STATUS_SUCCESS;
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.
}
}
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.
}
}
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.
}
}
cameraCount. 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.
peak_status errCode = PEAK_STATUS_SUCCESS;
// 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.
}
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);
if (peak_camera_id != PEAK_INVALID_CAMERA_ID)
{
// Got the camera id for the camera with the desired serial number.
// Open the camera.
peak_camera_handle hCam = PEAK_INVALID_HANDLE;
if (PEAK_ERROR(peak_Camera_Open(cameraID, &hCam)) == PEAK_TRUE)
{
// Opening the camera failed.
// Query the error details.
peak_status errCode = PEAK_STATUS_SUCCESS;
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.
peak_status errCode = PEAK_STATUS_SUCCESS;
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
}
}
An even simpler approach is demonstrated by this example:
const char serialNumber[] = "123456789";
peak_camera_handle hCam = PEAK_INVALID_HANDLE;
if (PEAK_ERROR(peak_Camera_Open(peak_Camera_ID_FromSerialNumber(serialNumber), &hCam)) == PEAK_TRUE)
{
// Opening the camera failed.
// Query the error details.
peak_status errCode = PEAK_STATUS_SUCCESS;
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.
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.
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))
{
case PEAK_ACCESS_READWRITE:
// The camera is available for use.
peak_camera_handle hCam = PEAK_INVALID_HANDLE;
peak_status status = peak_Camera_Open(camID, &hCam);
...
break;
case PEAK_ACCESS_NONE:
// 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;
case PEAK_ACCESS_INVALID:
// The access status query failed.
// Query the error details.
peak_status errCode = PEAK_STATUS_SUCCESS;
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;
}
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.
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:
if (PEAK_IS_WRITEABLE(peak_ExposureTime_GetAccessStatus(hCam)) == PEAK_TRUE)
{
// The exposure time feature is writeable.
peak_ExposureTime_Set(hCam, 100.0);
}
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:
const peak_access_status accessStatus = peak_ExposureTime_GetAccessStatus(hCam);
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
}
}
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.
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.
}
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.
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:
if (peak_PixelClock_HasRange(hCam) == PEAK_TRUE)
{
// 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);
}
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.
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.
This section provides explanations on the basic functioning of IDS peak comfortC.
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.
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_camera_handle hCam = PEAK_INVALID_HANDLE;
peak_frame_handle hFrame = PEAK_INVALID_HANDLE;
peak_buffer buffer = { NULL, 0, NULL };
peak_Library_Init();
peak_CameraList_Update(NULL);
peak_Camera_OpenFirstAvailable(&hCam);
peak_Acquisition_Start(hCam, 1);
peak_Acquisition_WaitForFrame(hCam, PEAK_INFINITE, &hFrame);
peak_Frame_Buffer_Get(hFrame, &buffer);
// The memory address where the image data starts is buffer.memoryAddress.
peak_Frame_Release(hCam, hFrame);
peak_Camera_Close(hCam);
peak_Library_Exit();
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.
peak_camera_handle hCam = PEAK_INVALID_HANDLE;
peak_frame_handle hFrame = PEAK_INVALID_HANDLE;
size_t requiredBufferCount = 0;
size_t requiredBufferSize = 0;
uint8_t** myBuffers = NULL;
peak_buffer buffer = { NULL, 0, NULL };
peak_Library_Init();
peak_CameraList_Update(NULL);
peak_Camera_OpenFirstAvailable(&hCam);
// 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_Acquisition_Start(hCam, 1);
peak_Acquisition_WaitForFrame(hCam, PEAK_INFINITE, &hFrame);
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_Camera_Close(hCam);
peak_Library_Exit();
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:
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.
if (peak_PixelClock_HasRange(hCam) == PEAK_TRUE)
{
// 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.
}
}
}
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: