Common Vision Blox 15.0
Loading...
Searching...
No Matches
Generic Data Container (GenDC)

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

  1. 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.
  2. 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>
// (...) connect to camera and create stream
// Get the prefetch descriptor with preliminary information
auto prefetchDescriptorInput = stream->GenDCPrefetchDescriptor();
// Start acquisition
stream->Start();
Cvb::WaitStatus waitStatus;
std::tie(composite, waitStatus, enumerator) = stream->WaitFor(std::chrono::milliseconds(100));
// this is the final descriptor with the actual information about the streamed payload
const auto &finalDescriptor = composite->GenDCFinalDescriptor();
WaitStatus
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>
// (...) get descriptor
// Component-level or part-level queries
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)) // check if it's a 2D part
{
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:

  1. Part Configurations (GenDcDescriptorPartConfig): Define PFNC format, flow ID, size, and offsets.
  2. Component Configurations (GenDcDescriptorComponentConfig): Group together one or more parts.
  3. 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;
// Define a part: 2D image part
Driver::GenDcDescriptorPartConfig imagePart(
GenDCPartType::Part2D,
PfncFormat::Mono8, // PFNC pixel format
0, // Flow ID
0, // Flow offset
640*480 // Data size in bytes
);
parts.emplace_back(imagePart);
// Add to a component
Driver::GenDcDescriptorComponentConfig component{ComponentId::Intensity, // e.g., an image component
PfncFormat::Mono8,
parts};
// Add component to descriptor config
Driver::GenDcDescriptorConfig descriptorConfig;
descriptorConfig.Components.emplace_back(component);
// Create descriptor
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.