Generic Data Container (GenDC) is a standardized data format for composite payloads transferred by GenTL compliant devices. It is part of the GenICam standard, defines a payload independent way of transporting data and allows for complex and variable sized data types. See GenICam for a detailed introduction on the GenICam standard behind the API. CVB hides this data format and the underlying data can be accessed using the CVB CompositeStream. However, to allow for advanced usage (e.g. in the GevServer), some knowledge of this format is recommended.
Description
The core difference to traditional payload transfer is, that the data description is packed within the streamed data. This detaches the properties of the data from the way the data stream is transmitted. The descriptor is a binary structure that contains metadata about the components, parts and their properties, such as its dimensions, pixel format, and other relevant information. This metadata is essential for correctly interpreting and processing the image data.
CVB GenDC Support
CVB supports GenDC descriptors for both fixed-size and variable-size payloads. The GenDC descriptor is typically provided by the devices stream or is attached to the actually streamed data. CVB provides functions to parse and interpret the GenDC descriptor, allowing users to easily extract its associated metadata.
Forms of descriptors
- Prefetch descriptor: The descriptor is provided before the actual data stream and describes the expected payloads and their limits. This allows the application to prepare for incoming data by allocating appropriate buffers and setting up processing pipelines based on the descriptor information.
- Final Descriptor: The descriptor is embedded within the payload data in order to describe the dynamic buffer traits. This approach is useful when the data format may change during streaming. However, the component/part size in the final descriptor can never exceed that provided by the prefetch descriptor.
Descriptors in CVB
Within CVB we can get both forms of descriptors as follows:
#include <cvb/driver/gendc_descriptor.hpp>
auto prefetchDescriptorInput = stream->GenDCPrefetchDescriptor();
stream->Start();
std::tie(composite, waitStatus, enumerator) = stream->WaitFor(std::chrono::milliseconds(100));
const auto &finalDescriptor = composite->GenDCFinalDescriptor();
std::shared_ptr< Composite > CompositePtr
The CVB descriptor classes provide methods to access the metadata carried in the GenDC descriptor and to create ones from scratch.
Querying Information from an Existing GenDC Descriptor
When a Cvb::GenDcDescriptor
is provided by a device (e.g., via a stream), it can be inspected using the C++ wrapper API. Descriptors contain components (e.g., images, metadata blocks), and each component contains one or more parts (e.g., 2D images, 1D metadata arrays, 3D pointclouds). For accessing top level container information there are getters for different properties, e.g., version, flags, container ID, data size, and variable fields. The data within containers is organized into components and parts, which can be accessed as follows:
#include <cvb/shims/optional.hpp>
for (const auto component : descriptor->GetComponents())
{
auto typeId = component.GetTypeId();
auto timestamp = component.GetTimestamp();
for (const auto &partVariant : component.GetParts())
{
const auto dataSize = Cvb::visit([&](const GenDcPart &part) -> size_t { return part.GetDataSize(); }, partVariant);
}
}
On the part level, different types of parts can be handled using Cvb::variant
and Cvb::visit
. The following part types are supported:
- Cvb::GenDcPart2D: Represents a 2D image part, providing access to properties like width, height, pixel format, and data size.
- Cvb::GenDcPart1D: Represents a 1D image part, providing access to properties size and padding.
- Cvb::GenDcPartH264: Represents an H.264 video stream part, providing access to properties like data size and codec-specific information.
- Cvb::GenDcPartMetadata: Represents a metadata part, providing access to properties like Size and Padding.
Using Cvb::visit
, you can handle specific part types accordingly, for example for a 2D image part:
for (const auto &partVariant : component.GetParts())
{
if(Cvb::holds_alternative<Cvb::GenDcPart2D>(partVariant))
{
const auto width = Cvb::visit([&](const GenDcPart2D &part) -> size_t { return part.GetSizeX(); }, partVariant);
const auto height = Cvb::visit([&](const GenDcPart2D &part) -> size_t { return part.GetSizeY(); }, partVariant);
}
}
Creating a GenDC Descriptor from Scratch
- Warning
- Creating an own GenDC descriptor is an advanced use case and requires a deep understanding of the GenDC standard.
In addition to reading descriptors, CVB allows creating custom GenDC descriptors. This is useful for user-defined containers, building test descriptors, or defining payloads for the CVB GigE Vision Server. The following example demonstrates how to create a simple GenDC descriptor with one image component. Descriptors are built hierarchically:
- Part Configurations (GenDcDescriptorPartConfig): Define PFNC format, flow ID, size, and offsets.
- Component Configurations (GenDcDescriptorComponentConfig): Group together one or more parts.
- Descriptor Configuration (GenDcDescriptorConfig) Aggregate multiple components.
The following example shows how to create a simple GenDC descriptor for an image with a specific pixel format and dimensions.
std::vector<GenDcDescriptorPartConfig> parts;
Driver::GenDcDescriptorPartConfig imagePart(
GenDCPartType::Part2D,
PfncFormat::Mono8,
0,
0,
640*480
);
parts.emplace_back(imagePart);
Driver::GenDcDescriptorComponentConfig component{ComponentId::Intensity,
PfncFormat::Mono8,
parts};
Driver::GenDcDescriptorConfig descriptorConfig;
descriptorConfig.Components.emplace_back(component);
const auto customDesc = Driver::GenDcDescriptor::Create(descriptorConfig);
The complexity of GenDC descriptors can vary significantly based on the application and data being represented. CVB's GenDC support provides a flexible and powerful way to work with these descriptors, whether they are provided by devices or created manually.
- Warning
- Be aware that implicit dependencies between fields within the descriptor have to be handled by the user. CVB does not enforce any constraints on the values set in the descriptor.