ADTF  3.18.2
Source Code for Demo Custom Stream Type Filters Plugin
Location
./src/examples/src/adtf/filters/standard_filters/custom_stream_type/
Namespace for entire ADTF SDK.
Build Environment
To see how to set up the build environment have a look at ADTF CMake Environment
this implementation shows:
Raw Stream Type
#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";
};
Copyright © Audi Electronics Venture GmbH.
char tChar
The tChar defines the type for platform character set (platform and compiler dependent type).
Raw Stream Type With a Property
#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);
}
};
Generator template to implement a ant::IStreamType based on a Stream Meta Type - see Stream Type and ...
Definition: streamtype.h:376
virtual T * Get() const =0
Get raw pointer to shared object.
Base object pointer to realize binary compatible reference counting in interface methods.
tResult set_property(IConfiguration &oConfiguration, const char *strNameOfValue, VALUETYPE oValue)
Set the property.
Example Sensor Data
#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 structure<tSensorData> get_sensor_data_type_definition()
{
return structure<tSensorData>("tSensorData").
Add("fDistance", &tSensorData::fDistance);
}
Stream Type With Data Definition and Properties
#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);
}
};
tResult set_media_description_properties(base::ant::IProperties &oProperties, const char *strStructName, const char *strMediaDescription, adtf_ddl::tDataRepresentation eRep=adtf_ddl::tDataRepresentation::Deserialized)
Adds the media description properties to a properties object.
Stream Type With Data Definition and Property that is required to match.
#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)
{
adtf::streaming::set_property<adtf::util::cString>(*this,
stream_meta_type_custom_sensor::SensorType,
strSensorType);
}
};
#define RETURN_ERROR_DESC(_code,...)
Same as RETURN_ERROR(_error) using a printf like parameter list for detailed error description.
#define RETURN_NOERROR
Return status ERR_NOERROR, which requires the calling function's return type to be tResult.
Defines access methods for the interface of a Stream Type - see also Stream Type and Stream Meta Type...
Generator Header
#pragma once
using namespace adtf::base;
using namespace adtf::streaming;
using namespace adtf::filter;
using namespace adtf::mediadescription;
class cCustomStreamTypesDataGenerator: public cFilter
{
public:
ADTF_CLASS_ID_NAME(cCustomStreamTypesDataGenerator,
"demo_custom_stream_types_generator.filter.adtf.cid",
"Demo Custom Stream Types Data Generator");
cCustomStreamTypesDataGenerator();
tResult Process(tNanoSeconds tmTrigger, IRunner* pRunner) override;
private:
ISampleWriter* m_pRawDataWriter = nullptr;
ISampleWriter* m_pRawDataWithPropertyWriter = nullptr;
ISampleWriter* m_pMountedSensorWriter = nullptr;
ISampleWriter* m_pSensorAWriter = nullptr;
ISampleWriter* m_pSensorBWriter = nullptr;
};
#define ADTF_CLASS_ID_NAME(_class, _strcid, _strclabel)
Common macro to enable correct treatment of class identifier AND Class Name by IClassInfo.
Definition: class_id.h:33
Copyright © Audi Electronics Venture GmbH.
Namespace for the ADTF Base SDK.
Namespace for the ADTF Filter SDK.
Namespace for the ADTF Media Description SDK.
Namespace for the ADTF Streaming SDK.
Generator Implementation
#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"
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/adtf_html/page_demo_custom_stream_type_filters.html");
}
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());
}
Accessor Header
#pragma once
using namespace adtf::base;
using namespace adtf::streaming;
using namespace adtf::filter;
using namespace adtf::mediadescription;
class cCustomStreamTypesDataAccess: public cFilter
{
public:
ADTF_CLASS_ID_NAME(cCustomStreamTypesDataAccess,
"demo_custom_stream_types_access.filter.adtf.cid",
"Demo Custom Stream Types Data Access");
cCustomStreamTypesDataAccess();
tResult AcceptType(ISampleReader* pReader, const iobject_ptr<const IStreamType>& pType) override;
tResult ProcessInput(ISampleReader* pReader, const iobject_ptr<const ISample>& pSample) override;
private:
ISampleReader* m_pRawDataReader = nullptr;
ISampleReader* m_pRawDataWithPropertyReader = nullptr;
ISampleReader* m_pUnspecifiedSensorReader = nullptr;
ISampleReader* m_pMountedSensorReader = nullptr;
ISampleReader* m_pSensorAReader = nullptr;
ISampleReader* m_pSensorBReader = nullptr;
int32_t m_nCurrentMyPropertyValue = 0;
struct tSensorMountPosition
{
double fX;
double fY;
double fZ;
};
tSensorMountPosition m_sSensorMountPosition;
};
Accessor Implementation
#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"
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/adtf_html/page_demo_custom_stream_type_filters.html");
}
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 RETURN_IF_FAILED(s)
Return if expression is failed, which requires the calling function's return type to be tResult.