Discovering Grabbers and Cameras
Using indices
In the previous example, we created a grabber object using the indices of the interface (CARD_IX) and device (DEVICE_IX) to use:
Euresys::EGrabber<> grabber(gentl, CARD_IX, DEVICE_IX);
Those indices are optional and are set to 0 by default. We have already seen earlier that GenTL modules are organized as a tree structure where the root is the system module (please refer to the chapter about GenTL modules for details). In short, the system module maintains a list of interfaces present in the system, each interface maintains a list of devices associated to that interface, and each device maintains a list of available data streams. So using 3 indices, we can identify a specific data stream within the GenTL module hierarchy. Each index represents the position of an element in 3 successive lists (interface, device and stream lists).
The GenTL standard defines two functions to update those lists:
● | TLUpdateInterfaceList: to update the list of available interfaces in the system; |
● | IFUpdateDeviceList: to update the list of available devices connected to a specific interface. |
Please note that the GenTL standard mandates that those lists cannot change between calls to their corresponding update functions. In other words, when TLUpdateInterfaceList is called, a “snapshot” of the present interfaces is taken and maintained in the GenTL library until the next call. The same applies to IFUpdateDeviceList for the available devices of a specific interface.
To simplify the creation of a grabber object, the EGrabber constructor calls the “update list” functions automatically so that the indices given as arguments refer to the current state of the system.
Those constructors are fine and easy to use when the system hierarchy is fixed, i.e. when it does not change dynamically.
Coaxlink series and Grablink cards are fixed interfaces in the system and those interfaces have a fixed number of devices that depends on the selected firmware. Calling several times the “update list” functions from the same process on such fixed systems will lead to the same results; therefore an application can safely use the indices to identify specific modules and create grabbers.
However, this simple approach may lead to troubles on systems that change dynamically. The Gigelink producer is a system that uses network interfaces to find and establish connections to GigE Vision cameras. Obviously, calling IFUpdateDeviceList on such systems will lead to completely different results depending on what’s available on the network when the function is invoked. In such environments, referring to a specific data stream using indices might not be applicable.
To solve this issue, and to provide a simple way to discover possible grabber objects and connected cameras in the system, we provide the Euresys::EGrabberDiscovery module.
Using EGrabberDiscovery
The Euresys::EGrabberDiscovery module provides a function discover that scans the system to detect available grabbers and cameras. Here is an example:
#include <EGrabber.h>
static void discover() {
Euresys::EGenTL gentl;
Euresys::EGrabberDiscovery discovery(gentl); // 1
discovery.discover(); // 2
for (int i = 0; i < discovery.egrabberCount(); ++i) { // 3
EGrabber<CallbackOnDemand> grabber(discovery.egrabbers(i)); // 4
...
}
for (int i = 0; i < discovery.cameraCount(); ++i) { // 5
EGrabber<CallbackOnDemand> grabber(discovery.cameras(i)); // 6
...
}
}
1. | Create a Euresys::EGrabberDiscovery object for a specific producer (gentl argument). The object takes exclusive control of the producer interface and device lists. As long as the discovery object exists, it prevents any other module to update the lists. |
2. | Update the producer interface and device lists and scan the system to discover the available GenTL modules as well as the connected cameras at that moment. |
3. | Walk through the discovered grabbers. |
4. | For each discovered grabber, create a Euresys::EGrabber object; the function discovery::egrabbers returns the relevant information that identifies the discovered grabber for which a Euresys::EGrabber instance should be created. |
5. | Walk through the discovered cameras. |
6. | For each discovered camera, create a Euresys::EGrabber object; the function discovery::cameras returns the relevant information that identifies the discovered camera for which a Euresys::EGrabber instance should be created. |
Remarks
● | The Euresys::EGrabberDiscovery provides two ways of exploring the system, a grabber-oriented one and a camera-oriented one. The camera-oriented discovery is useful in at least two situations: |
□ | When an application needs to configure and/or use the cameras connected to the system (and simply ignore the unused grabbers). |
□ | When a multi-bank camera is connected to the system; a multi-bank camera is a camera composed by several cameras (which act as independent CoaXPress devices). In this case, each camera bank is connected to a specific GenTL device and exposes a data stream. The camera-oriented discovery is able1 to (1) detect automatically the different banks that make up the multi-bank camera, (2) reorder them, and (3) expose them as a unified camera that can be easily instantiated as an Euresys::EGrabber object. The resulting Euresys::EGrabber object hides the complexity of the banks and behaves as a usual EGrabber object as far as acquisition is concerned. |
● | As long as Euresys::EGrabberDiscovery exists, any attempt to update interface or device lists will trigger a not_allowed exception; this will happen if a Euresys::EGrabber object is created using the index-based constructor instead of the “discovery” variants because the index-based constructor updates the interface and device lists before opening the requested GenTL modules. |
Please refer to the Euresys::EGrabberDiscovery module documentation for a detailed description of the API.