CVB++ 15.0
Cvb/CppRdma
1// ---------------------------------------------------------------------------
4// ---------------------------------------------------------------------------
5
6#include <iostream>
7#include <string>
8#include <vector>
9
10#include <cvb/device_factory.hpp>
11#include <cvb/global.hpp>
12#include <cvb/driver/composite_stream.hpp>
13#include <cvb/genapi/node_map_enumerator.hpp>
14
15static const constexpr auto TIMEOUT = std::chrono::milliseconds(3000);
16static const constexpr int NUM_ELEMENTS_TO_ACQUIRE = 5000; // number of elements to be acquired
17static const constexpr int FEEDBACK_INTERVAL = NUM_ELEMENTS_TO_ACQUIRE / 10; // print progress
18static const constexpr int NUM_FLOW_SETS = 10; // number flow sets to announce (usually buffers)
19
20int main()
21{
22 try
23 {
24 // RDMA transfer is part of the socket driver (GevSD) so the filter driver (GevFD) must be ignored.
25 auto itemList = Cvb::DeviceFactory::Discover(Cvb::DiscoverFlags::IgnoreVins | Cvb::DiscoverFlags::IgnoreGevFD);
26
27 // The following will only work if there is a RDMA capable device connected to an RDMA capable
28 // network interface. Usually also a driver that allows user space access is required. See also
29 // * Windows: Network Direct Service Provider Interface (NDSPI)
30 // * Linux: librdmacm.so and libibverbs.so
31 auto& item = itemList.at(0);
32 // RDMA must be switched on explicitly otherwise the classic GVSP protocol will be used.
33 // This is just a request and may fail silently if RDMA is not supported.
34 // To verify that RDMA is supported and switched on you can check
35 // the "GevDataStreamingMode" in the TLDevice (Cvb::NodeMapID::TLDevice) node map and validate that it is
36 // set to "RDMA". The "RDMA" entry is only available if the device is RDMA capable.
37 item.SetParameter(CVB_LIT("UseRdma"), CVB_LIT("1"));
38
39
40 auto device = Cvb::DeviceFactory::Open<Cvb::GenICamDevice>(item.AccessToken(), Cvb::AcquisitionStack::GenTL);
41 auto payloadSize = static_cast<double>(device->NodeMap(Cvb::NodeMapID::Device)->Node<Cvb::IntegerNode>(CVB_LIT("PayloadSize"))->Value());
42 // Note that RDMA requires GenDC containers as payload.
43 // The container will automatically be mapped to a composite for
44 // further processing.
45 auto dataStream = device->Stream<Cvb::CompositeStream>();
46
47 // The default and minimal number of flow sets is three but it is usually
48 // advisable to increase the number so that about one second can be buffered.
49 dataStream->RegisterManagedFlowSetPool(NUM_FLOW_SETS);
50
51
52 dataStream->Start();
54 for (auto i = 0; i < NUM_ELEMENTS_TO_ACQUIRE; i++)
55 {
56 Cvb::CompositePtr composite;
57 Cvb::WaitStatus waitStatus;
58 Cvb::NodeMapEnumerator enumerator;
59 std::tie(composite, waitStatus, enumerator) = dataStream->WaitFor(TIMEOUT);
60 switch (waitStatus)
61 {
62 default:
63 // abort cannot happen in single threaded scenarios
65 throw std::runtime_error("wait status unknown.");
66
68 throw std::runtime_error("time out during wait");
69
71 break;
72 }
73
74 if (i && i % FEEDBACK_INTERVAL == 0)
75 {
76 // try to get the composite's first element as an image
77 auto firstElement = composite->ItemAt(0);
78 if (!Cvb::holds_alternative<Cvb::ImagePtr>(firstElement))
79 {
80 std::cout << "acquired composites: " << i << " which is not an image" << std::endl;
81 }
82 else
83 {
84 auto image = Cvb::get<Cvb::ImagePtr>(firstElement);
85 std::cout << "acquired images: " << i << " | size: " << image->Width() << " x " << image->Height() << std::endl;
86 }
87 }
88 }
90 auto durationMs = std::chrono::duration_cast<std::chrono::milliseconds>(endTime - startTime).count();
91 dataStream->TryAbort();
92
93 // For RDMA streaming the data rate is usually interesting...
94 auto dataRate = static_cast<int>((static_cast<double>(NUM_ELEMENTS_TO_ACQUIRE) * payloadSize) / (1000.0 * static_cast<double>(durationMs)));
95 std::cout << std::endl << "acquired " << NUM_ELEMENTS_TO_ACQUIRE << " buffers in " << durationMs << " ms ( " << dataRate << " MB/s )" << std::endl;
96 }
97 catch (const std::exception& e)
98 {
99 std::cout << e.what() << std::endl;
100 }
101 return 0;
102}
103
static std::vector< DiscoveryInformation > Discover()
Discovers available devices (not vins) with a default time span of 300ms.
Definition: decl_device_factory.hpp:221
void RegisterManagedFlowSetPool(int flowSetCount)
Registers an internal flows set pool.
Definition: decl_composite_stream_base.hpp:291
Streams composites.
Definition: composite_stream.hpp:21
Represents a integer number.
Definition: integer_node.hpp:20
Lazy enumeration of node maps.
Definition: node_map_enumerator.hpp:31
WaitStatus
Status after waiting for an image to be returned.
Definition: global.hpp:376
@ Abort
The acquisition has been stopped asynchronously, there is no image buffer.
@ Ok
Everything is fine, a new image arrived.
@ Timeout
A timeout occurred, no image buffer has been returned.