ADTF
Loading...
Searching...
No Matches
Example Demo Custom Stream Type

Description

Shows how to create own stream meta types.

Prebuilt Binaries

Source Code

./examples/demo_adtfplugins/demo_custom_stream_type/

Common

sensor_data.h

#pragma once
// this is an example data structure for sensor data.
struct tSensorData
{
double fDistance;
};
// this is a covenience method that creates a media description structure definition for tSensorData.
// A Media Description/DDL will be generated from this.
inline adtf::mediadescription::structure<tSensorData> get_sensor_data_type_definition()
{
Add("fDistance", &tSensorData::fDistance);
}
Definition type_reflection.h:124

Stream Types

stream_type_custom_sensor.h

#pragma once
#include "sensor_data.h"
// This is a stream meta type, that also defines an IsCompatible method.
// This way you can ensure that only stream types with matching Property values
// are accepted by Input Pins and Readers.
struct stream_meta_type_custom_sensor
{
static constexpr const tChar* const MetaTypeName = "demo/custom_sensor";
static constexpr const tChar* const SensorType = "sensor_type";
static void SetProperties(const adtf::ucom::iobject_ptr<adtf::base::IProperties>& pProperties)
{
adtf::base::set_property(*pProperties.Get(), SensorType, "");
// this will set the md_description, md_struct etc. properties based on the type definition.
adtf::mediadescription::set_media_description_properties(*pProperties.Get(), get_sensor_data_type_definition());
}
static tResult IsCompatible(const adtf::streaming::IStreamType& oTypeToCheck,
const adtf::streaming::IStreamType& oTypeExpected)
{
auto strSourceSensorType = adtf::streaming::get_property<adtf::util::cString>(oTypeToCheck, SensorType);
auto strDestSensorType = adtf::streaming::get_property<adtf::util::cString>(oTypeExpected, SensorType);
if (strSourceSensorType != strDestSensorType)
{
RETURN_ERROR_DESC(ERR_FAILED,
"The required destination sensor type '%s' differs from the source sensor type '%s'",
strSourceSensorType.GetPtr(),
strDestSensorType.GetPtr());
}
}
};
// and another helper class to create a stream type with the given property values.
struct stream_type_custom_sensor: public adtf::streaming::stream_type<stream_meta_type_custom_sensor>
{
stream_type_custom_sensor() = default;
stream_type_custom_sensor(const char* strSensorType)
{
stream_meta_type_custom_sensor::SensorType,
strSensorType);
}
};
A_UTILS_NS::cResult tResult
For backwards compatibility and to bring latest version into scope.
Definition result.h:736
#define RETURN_ERROR_DESC(_code,...)
Same as RETURN_ERROR(_error) using a printf like parameter list for detailed error description.
Definition result.h:44
#define RETURN_NOERROR
Return status ERR_NOERROR, which requires the calling function's return type to be tResult.
Definition result.h:29
Defines access methods for the interface of a Stream Type.
Definition streamtype_intf.h:96
Definition streamtype.h:368
virtual T * Get() const =0
Get raw pointer to shared object.
tResult set_property(IConfiguration &oConfiguration, const char *strNameOfValue, VALUETYPE oValue)
Set the property.
Definition configuration.h:327
tResult set_media_description_properties(base::ant::IProperties &oProperties, const char *strStructName, const char *strMediaDescription, ddl::tDataRepresentation eRep=ddl::tDataRepresentation::Deserialized)
VALUETYPE get_property(const IStreamType &oStreamType, const char *strNameOfValue, VALUETYPE oDefaultValue)
Definition streamtype_intf.h:287
tResult set_property(IStreamType &oStreamType, const char *strNameOfValue, VALUETYPE oValue)
Definition streamtype_intf.h:257
ant::iobject_ptr< T > iobject_ptr
Alias always bringing the latest version of ant::iobject_ptr into scope.
Definition object_ptr_intf.h:437

stream_type_mounted_sensor.h

#pragma once
#include "sensor_data.h"
// This a stream type that has some properties and a description of the sample data.
// Input Pins with this type, will accept any streams that have the same meta type (name),
// no matter which values the properties are set to.
struct stream_meta_type_mounted_sensor
{
static constexpr const tChar* const MetaTypeName = "demo/mounted_sensor";
static constexpr const tChar* const SensorMountX = "sensor_mount_x";
static constexpr const tChar* const SensorMountY = "sensor_mount_y";
static constexpr const tChar* const SensorMountZ = "sensor_mount_z";
static void SetProperties(const adtf::ucom::iobject_ptr<adtf::base::IProperties>& pProperties)
{
adtf::base::set_property(*pProperties.Get(), SensorMountX, 0.0);
adtf::base::set_property(*pProperties.Get(), SensorMountY, 0.0);
adtf::base::set_property(*pProperties.Get(), SensorMountZ, 0.0);
// this will set the md_description, md_struct etc. properties based on the type definition.
adtf::mediadescription::set_media_description_properties(*pProperties.Get(), get_sensor_data_type_definition());
}
// if we do not define an IsCompatible method readers will check only if the meta type name matches
};
// once again a helper class to create a stream type with the given property values.
struct stream_type_mounted_sensor: public adtf::streaming::stream_type<stream_meta_type_mounted_sensor>
{
stream_type_mounted_sensor() = default;
stream_type_mounted_sensor(double fMountX,
double fMountY,
double fMountZ)
{
adtf::streaming::set_property(*this, stream_meta_type_mounted_sensor::SensorMountX, fMountX);
adtf::streaming::set_property(*this, stream_meta_type_mounted_sensor::SensorMountY, fMountY);
adtf::streaming::set_property(*this, stream_meta_type_mounted_sensor::SensorMountZ, fMountZ);
}
};

stream_type_raw.h

#pragma once
// This is the most simple stream meta type, it just defines a name
// Everyone who uses this type has to know exactly what to do with the stream data
// as this provides no further information.
struct stream_meta_type_raw_data_that_only_i_understand
{
static constexpr const tChar* const MetaTypeName = "demo/raw_data_that_only_i_understand";
};

stream_type_raw_with_properties.h

#pragma once
// This is a stream meta type that has a property
// This still has no defintion of the data structures that the samples contain.
// Everyone has to aggree on how to interpret sample data via other mechanisms.
struct stream_meta_type_raw_data_with_properties
{
static constexpr const tChar* const MetaTypeName = "demo/raw_data_with_properties";
static constexpr const tChar* const MyProperty = "my_property";
static void SetProperties(const adtf::ucom::iobject_ptr<adtf::base::IProperties>& pProperties)
{
adtf::base::set_property<int32_t>(*pProperties.Get(), MyProperty, 0);
}
// if we do not define an IsCompatible method readers will check only if the meta type name matches
};
// This is a helper class to easily create a stream type instance, set the stream meta type to
// stream_meta_type_raw_data_with_properties and set the property to a given value.
// without this, you would need to write the following snippet, that does the same:
//
// auto pType = make_object_ptr<cStreamType>(stream_meta_type_raw_data_with_properties());
// adtf::streaming::set_property(*pType, stream_meta_type_raw_data_with_properties::MyProperty, 123);
// CreateOutputPin("output", pType);
//
// instead of
//
// CreateOutputPin("output", stream_type_raw_data_with_properties(123));
//
struct stream_type_raw_data_with_properties: public adtf::streaming::stream_type<stream_meta_type_raw_data_with_properties>
{
stream_type_raw_data_with_properties() = default;
stream_type_raw_data_with_properties(int nMyProperty)
{
adtf::streaming::set_property(*this, stream_meta_type_raw_data_with_properties::MyProperty, nMyProperty);
}
};

Access

demo_custom_stream_type_access_filter.h

#pragma once
#ifndef ADTF_EXAMPLES_CID
#define ADTF_EXAMPLES_CID ".local.cid"
#endif
class cCustomStreamTypesDataAccess final : public adtf::filter::cFilter
{
public:
ADTF_CLASS_ID_NAME(cCustomStreamTypesDataAccess,
"demo_custom_stream_types_access.filter" ADTF_EXAMPLES_CID,
"Demo Custom Stream Types Data Access");
cCustomStreamTypesDataAccess();
~cCustomStreamTypesDataAccess() override;
private:
adtf::streaming::ISampleReader* m_pRawDataReader = nullptr;
adtf::streaming::ISampleReader* m_pRawDataWithPropertyReader = nullptr;
adtf::streaming::ISampleReader* m_pUnspecifiedSensorReader = nullptr;
adtf::streaming::ISampleReader* m_pMountedSensorReader = nullptr;
adtf::streaming::ISampleReader* m_pSensorAReader = nullptr;
adtf::streaming::ISampleReader* m_pSensorBReader = nullptr;
int32_t m_nCurrentMyPropertyValue = 0;
struct tSensorMountPosition
{
double fX;
double fY;
double fZ;
};
tSensorMountPosition m_sSensorMountPosition;
};
#define ADTF_CLASS_ID_NAME(_class, _strcid, _strclabel)
Definition class_id.h:33
Definition filter.h:289
virtual tResult ProcessInput(base::flash::tNanoSeconds tmTrigger, streaming::flash::ISampleReader *pReader)
virtual tResult AcceptType(streaming::flash::ISampleReader *pReader, const ucom::ant::iobject_ptr< const streaming::ant::IStreamType > &pType)
Definition samplestreamer_intf.h:188

demo_custom_stream_type_access_filter.cpp

#include "demo_custom_stream_type_access_filter.h"
#include "stream_type_raw.h"
#include "stream_type_raw_with_properties.h"
#include "stream_type_mounted_sensor.h"
#include "stream_type_custom_sensor.h"
#include "sensor_data.h"
using namespace adtf::base;
using namespace adtf::streaming;
using namespace adtf::filter;
using namespace adtf::mediadescription;
cCustomStreamTypesDataAccess::cCustomStreamTypesDataAccess()
{
// this pin accepts only streams with the given stream_meta_type
m_pRawDataReader = CreateInputPin("raw", stream_meta_type_raw_data_that_only_i_understand());
SetDescription("raw", "Input data based on raw stream type");
// this pin accepts only streams with the given stream_meta_type, we will access property later on.
m_pRawDataWithPropertyReader = CreateInputPin("raw_with_property", stream_type_raw_data_with_properties());
SetDescription("raw_with_property", "Input data based on a raw stream type with setted property");
// this pin accepts any stream that transmits samples that contain tSensorData.
m_pUnspecifiedSensorReader = CreateInputPin("unspecified_sensor", get_sensor_data_type_definition());
SetDescription("unspecified_sensor", "Input data for an unspecified sensor");
// this pin accepts only streams of stream_meta_type_mounted_sensor, but we don't care about specific property values.
m_pMountedSensorReader = CreateInputPin("mounted_sensor", stream_type_mounted_sensor());
SetDescription("mounted_sensor", "Input data compatible with a specified mounted_sensor");
// this pin accepts only streams of stream_meta_type_custom_sensor, where the sensor type must match "SensorA".
m_pSensorAReader = CreateInputPin("sensor_a", stream_type_custom_sensor("SensorA"));
SetDescription("sensor_a", "Input data compatible with a specified Sensor A");
// this pin accepts only streams of stream_meta_type_custom_sensor, where the sensor type must match "SensorB".
m_pSensorBReader = CreateInputPin("sensor_b", stream_type_custom_sensor("SensorB"));
SetDescription("sensor_b", "Input data compatible with a specified Sensor B");
// sets a short description for the component
SetDescription("Use this filter to print received streaming data based on several custom stream types.");
// set help link to jump to documentation from ADTF Configuration Editor
SetHelpLink("$(ADTF_DIR)/doc/html/page_demo_custom_stream_types_data_access.html");
}
cCustomStreamTypesDataAccess::~cCustomStreamTypesDataAccess() = default;
tResult cCustomStreamTypesDataAccess::AcceptType(ISampleReader* pReader, const iobject_ptr<const IStreamType>& pType)
{
// we want the default compatibility behaviour, so we call the base method first.
RETURN_IF_FAILED(cFilter::AcceptType(pReader, pType));
if (pReader == m_pRawDataWithPropertyReader)
{
// if we received a new type, we read its property value and store it.
// you could of course store the stream type instance as well, but we ar only interested in the property value.
m_nCurrentMyPropertyValue = get_property<int>(*pType.Get(), stream_meta_type_raw_data_with_properties::MyProperty);
}
else if (pReader == m_pMountedSensorReader)
{
// update the mount position.
m_sSensorMountPosition = {get_property<double>(*pType.Get(), stream_meta_type_mounted_sensor::SensorMountX),
get_property<double>(*pType.Get(), stream_meta_type_mounted_sensor::SensorMountY),
get_property<double>(*pType.Get(), stream_meta_type_mounted_sensor::SensorMountZ) };
}
}
tResult cCustomStreamTypesDataAccess::ProcessInput(ISampleReader* pReader, const iobject_ptr<const ISample>& pSample)
{
if (pReader == m_pRawDataReader)
{
LOG_INFO("received a raw sample");
}
else if (pReader == m_pRawDataWithPropertyReader)
{
LOG_INFO("received a raw sample, my_property is currently %d", m_nCurrentMyPropertyValue);
}
else if (pReader == m_pUnspecifiedSensorReader)
{
LOG_INFO("received a distance reading from unspecified sensor: %f",
sample_data<tSensorData>(pSample)->fDistance);
}
else if (pReader == m_pMountedSensorReader)
{
LOG_INFO("received a distance reading from sensor mounted at (%f, %f, %f): %f",
m_sSensorMountPosition.fX,
m_sSensorMountPosition.fY,
m_sSensorMountPosition.fZ,
sample_data<tSensorData>(pSample)->fDistance);
}
else if (pReader == m_pSensorAReader)
{
LOG_INFO("received a distance reading from sensor A: %f",
sample_data<tSensorData>(pSample)->fDistance);
}
else if (pReader == m_pSensorBReader)
{
LOG_INFO("received a distance reading from sensor B: %f",
sample_data<tSensorData>(pSample)->fDistance);
}
}
#define LOG_INFO(...)
Logs an info message.
Definition log.h:388
Definition sample_data.h:429
Namespace for the ADTF Base SDK.
Definition adtf_base_type_traits.h:13
VALUETYPE get_property(const IConfiguration &oConfiguration, const char *strNameOfValue, VALUETYPE oDefaultValue)
Get the property content converted to the VALUETYPE.
Definition configuration.h:291
Namespace for the ADTF Filter SDK.
Definition configurable_runner.h:18
Namespace for the ADTF Mediadescription SDK.
Definition codec_sample_streamer.h:22
Namespace for the ADTF Streaming SDK.
Definition bindingproxyinport.h:14

Generator

demo_custom_stream_type_generator_filter.h

#pragma once
#ifndef ADTF_EXAMPLES_CID
#define ADTF_EXAMPLES_CID ".local.cid"
#endif
class cCustomStreamTypesDataGenerator final : public adtf::filter::cFilter
{
public:
ADTF_CLASS_ID_NAME(cCustomStreamTypesDataGenerator,
"demo_custom_stream_types_generator.filter" ADTF_EXAMPLES_CID,
"Demo Custom Stream Types Data Generator");
cCustomStreamTypesDataGenerator();
~cCustomStreamTypesDataGenerator() override;
private:
adtf::streaming::ISampleWriter* m_pRawDataWriter = nullptr;
adtf::streaming::ISampleWriter* m_pRawDataWithPropertyWriter = nullptr;
adtf::streaming::ISampleWriter* m_pMountedSensorWriter = nullptr;
adtf::streaming::ISampleWriter* m_pSensorAWriter = nullptr;
adtf::streaming::ISampleWriter* m_pSensorBWriter = nullptr;
};
virtual tResult Process(base::flash::tNanoSeconds tmTrigger, streaming::ant::IRunner *pRunner)
Definition runner_intf.h:24
Definition samplestreamer_intf.h:234
A timestamp with nanosecond precision.
Definition chrono.h:23

demo_custom_stream_type_generator_filter.cpp

#include "demo_custom_stream_type_generator_filter.h"
#include "stream_type_raw.h"
#include "stream_type_raw_with_properties.h"
#include "stream_type_mounted_sensor.h"
#include "stream_type_custom_sensor.h"
using namespace adtf::base;
using namespace adtf::streaming;
using namespace adtf::filter;
using namespace adtf::mediadescription;
cCustomStreamTypesDataGenerator::cCustomStreamTypesDataGenerator()
{
m_pRawDataWriter = CreateOutputPin("raw", stream_meta_type_raw_data_that_only_i_understand());
SetDescription("raw", "Provides data compatible with raw stream type");
m_pRawDataWithPropertyWriter = CreateOutputPin("raw_with_property", stream_type_raw_data_with_properties(42));
SetDescription("raw_with_property", "Provides data compatible with raw stream type with setted property");
m_pMountedSensorWriter = CreateOutputPin("mounted_sensor", stream_type_mounted_sensor(1.0, 2.0, 3.0));
SetDescription("mounted_sensor", "Provides data compatible with mounted_sensor");
m_pSensorAWriter = CreateOutputPin("sensor_a", stream_type_custom_sensor("SensorA"));
SetDescription("sensor_a", "Provides data compatible with Sensor A");
m_pSensorBWriter = CreateOutputPin("sensor_b", stream_type_custom_sensor("SensorB"));
SetDescription("sensor_b", "Provides data compatible with Sensor B");
CreateRunner("generate_data", cTimerTriggerHint(std::chrono::seconds{1}));
SetDescription("generate_data", "Runner to periodically trigger the function which generates the output samples");
// sets a short description for the component
SetDescription("Use this filter to generate data based on several custom stream types.");
// set help link to jump to documentation from ADTF Configuration Editor
SetHelpLink("$(ADTF_DIR)/doc/html/page_demo_custom_stream_types_data_generator.html");
}
cCustomStreamTypesDataGenerator::~cCustomStreamTypesDataGenerator() = default;
tResult cCustomStreamTypesDataGenerator::Process(tNanoSeconds tmTrigger, IRunner* /*pRunner*/)
{
output_sample_data<uint8_t> oRawData(tmTrigger, 123);
m_pRawDataWriter->Write(oRawData.Release());
output_sample_data<uint8_t> oRawDataWithProperty(tmTrigger, 123);
m_pRawDataWithPropertyWriter->Write(oRawDataWithProperty.Release());
output_sample_data<tSensorData> oMountedSensorData(tmTrigger, {3.1415});
m_pMountedSensorWriter->Write(oMountedSensorData.Release());
output_sample_data<tSensorData> oSensorAData(tmTrigger, {3.1415});
m_pSensorAWriter->Write(oSensorAData.Release());
output_sample_data<tSensorData> oSensorBData(tmTrigger, {-3.1415});
m_pSensorBWriter->Write(oSensorBData.Release());
}

Plugin

plugin.cpp

#include "demo_string_sending_filter.h"
#include "demo_string_receiving_filter.h"
ADTF_PLUGIN("Demo String Handling Filters Plugin",
cDemoStringSending,
cDemoStringReceiving);
#define ADTF_PLUGIN(__plugin_identifier,...)
Definition adtf_plugin.h:29