ADTF
Loading...
Searching...
No Matches
Example Demo Time Trigger

Description

Shows how to implement a filter which is triggered by a Timer Runner.

Additionally, it show how to use DDL type reflection API to create valid description from a cpp defined struct:

  • simple structured and nested structured data
  • array of plain data types
  • array of structured data
  • array with valid element count
  • valid flag for a single data element

Prebuilt Binaries

Source Code

./examples/demo_adtfplugins/demo_time_trigger/

Filter

demo_time_trigger_function.h

#pragma once
#include <random>
#include <functional>
#ifndef ADTF_EXAMPLES_CID
#define ADTF_EXAMPLES_CID ".local.cid"
#endif
class cSimpleDataGenerator final : public adtf::filter::cFilter
{
public:
ADTF_CLASS_ID_NAME(cSimpleDataGenerator, "demo_time_trigger.filter" ADTF_EXAMPLES_CID, "Demo Time Trigger");
public:
cSimpleDataGenerator();
~cSimpleDataGenerator() override;
tResult Init(tInitStage eStage) override;
void GenerateSimpleData(adtf::base::tNanoSeconds tmTimeOfTrigger, double fOutValue);
void GenerateSimpleArrayData(adtf::base::tNanoSeconds tmTimeOfTrigger, double fOutValue);
void GenerateNestedData(adtf::base::tNanoSeconds tmTimeOfTrigger, double fOutValue);
void GenerateNestedArrayData(adtf::base::tNanoSeconds tmTimeOfTrigger, double fOutValue);
void GenerateArraysWithValidElementCountData(adtf::base::tNanoSeconds tmTimeOfTrigger, double fOutValue);
private:
// writer to an output pin for simple plain types
adtf::streaming::ISampleWriter* m_pWriterSimple = nullptr;
// writer to an output pin for simple plain array type
adtf::streaming::ISampleWriter* m_pWriterSimpleArray = nullptr;
// writer to an output pin structured types
adtf::streaming::ISampleWriter* m_pWriterNested = nullptr;
// writer to an output pin for structured array types
adtf::streaming::ISampleWriter* m_pWriterNestedArray = nullptr;
// writer to an output pin for structured array types with valid element counts
adtf::streaming::ISampleWriter* m_pWriterArraysWithValidElementCount = nullptr;
// a counter
uint64_t m_nCounter = 0;
// valid ec counter for the array with valid element count
uint64_t m_nValidElementCountCounter = 0;
// to generate random numbers
std::mt19937 m_oRandomGenerator;
std::uniform_real_distribution<double> m_oDistribution;
// the selected generator method
std::function<double()> m_fnGenerator;
enum tGeneratorType : uint32_t
{
eCounter = 0,
eRandom = 1
};
// this will reflect any property changes.
adtf::base::property_variable<tGeneratorType> m_eGeneratorType = eCounter;
};
A_UTILS_NS::cResult tResult
For backwards compatibility and to bring latest version into scope.
Definition result.h:736
#define ADTF_CLASS_ID_NAME(_class, _strcid, _strclabel)
Definition class_id.h:33
Property Variable template for the given T. A Property Variable will store a copy of a property value...
Definition configuration.h:808
Definition filter.h:289
tResult Init(tInitStage eStage) override
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_time_trigger_function.cpp

#include "demo_time_trigger_function.h"
#include <easy/profiler.h>
using namespace adtf::util;
using namespace ddl;
using namespace adtf::ucom;
using namespace adtf::base;
using namespace adtf::streaming;
using namespace adtf::mediadescription;
using namespace adtf::filter;
namespace
{
#pragma pack(push, 1)
enum class eSimpleEnum : tUInt8
{
eEnum_value_zero = 0,
eEnum_value_one = 1,
eEnum_value_two = 2,
eEnum_value_three = 3,
eEnum_value_four = 4,
eEnum_value_five = 5,
eEnum_value_six = 6,
eEnum_value_seven = 7,
eEnum_value_eight = 8,
eEnum_value_nine = 9
};
struct tSimpleStruct
{
uint8_t ui8Val;
uint16_t ui16Val;
uint32_t ui32Val;
int32_t i32Val;
int64_t i64Val;
double f64Val;
float f32Val;
eSimpleEnum ei8EnumVal;
};
struct tSimpleStructArray
{
int32_t i32SimpleValidElementCount;
tSimpleStruct sSimple[10];
};
struct tHeaderStruct
{
uint32_t ui32HeaderVal;
double f64HeaderVal;
};
struct tNestedStruct
{
tHeaderStruct sHeaderStruct;
tSimpleStruct sSimpleStruct;
};
struct tNestedArrayStruct
{
tHeaderStruct sHeaderStructArray[100];
tSimpleStruct sSimpleStructArray[2000];
};
struct tArraysWithValidElementCount
{
uint32_t nSimpleStructArrayValidElementCount;
tSimpleStructArray sSimpleStructArray[20];
uint64_t nArrayValidElementCount;
int64_t nArray[30];
int64_t nValue;
bool bValueValid; // marks the nValue as valid or not
};
#pragma pack(pop)
}
// this creates the plugin entry methods and class factories
ADTF_PLUGIN("Demo Time Trigger Plugin", cSimpleDataGenerator);
cSimpleDataGenerator::cSimpleDataGenerator(): m_oDistribution(0.0, 100.0)
{
// create the pin for plain types
m_pWriterSimple = CreateOutputPin("out", stream_type_plain<float>());
SetDescription("out", "Provides the generated data based on number_gen_type");
// create the pin for plain array types
m_pWriterSimpleArray = CreateOutputPin("out_array", stream_type_plain<std::array<int64_t, 10>>());
SetDescription("out_array", "Provides the generated data array based on number_gen_type");
const auto oSimpleEnumDefinition = enumeration<eSimpleEnum>("eSimpleEnum")
.Add("eEnum_value_zero", eSimpleEnum::eEnum_value_zero)
.Add("eEnum_value_one", eSimpleEnum::eEnum_value_one)
.Add("eEnum_value_two", eSimpleEnum::eEnum_value_two)
.Add("eEnum_value_three", eSimpleEnum::eEnum_value_three)
.Add("eEnum_value_four", eSimpleEnum::eEnum_value_four)
.Add("eEnum_value_five", eSimpleEnum::eEnum_value_five)
.Add("eEnum_value_six", eSimpleEnum::eEnum_value_six)
.Add("eEnum_value_seven", eSimpleEnum::eEnum_value_seven)
.Add("eEnum_value_eight", eSimpleEnum::eEnum_value_eight)
.Add("eEnum_value_nine", eSimpleEnum::eEnum_value_nine);
// define our data type from an existing struct definition
auto oSimpleStructDefinition = structure<tSimpleStruct>("tSimpleStruct");
oSimpleStructDefinition.createElement("ui8Val", &tSimpleStruct::ui8Val);
oSimpleStructDefinition.createElement("ui16Val", &tSimpleStruct::ui16Val);
oSimpleStructDefinition.createElement("ui32Val", &tSimpleStruct::ui32Val);
oSimpleStructDefinition.createElement("i32Val", &tSimpleStruct::i32Val);
oSimpleStructDefinition.createElement("i64Val", &tSimpleStruct::i64Val);
oSimpleStructDefinition.createElement("f64Val", &tSimpleStruct::f64Val);
oSimpleStructDefinition.createElement("f32Val", &tSimpleStruct::f32Val);
oSimpleStructDefinition.createElement("ei8EnumVal", &tSimpleStruct::ei8EnumVal, oSimpleEnumDefinition);
// definition which used the previously defined defintion in an array and has a valid element count
auto oSimpleStructArrayDefinition = structure<tSimpleStructArray>("tSimpleStructArray");
oSimpleStructArrayDefinition.createElement("i32SimpleValidElementCount",
&tSimpleStructArray::i32SimpleValidElementCount);
oSimpleStructArrayDefinition.createElement("sSimple", &tSimpleStructArray::sSimple, oSimpleStructDefinition)
.setValidElementCount("i32SimpleValidElementCount");
auto oHeaderStructDefinition = structure<tHeaderStruct>("tHeaderStruct");
oHeaderStructDefinition.createElement("ui32HeaderVal", &tHeaderStruct::ui32HeaderVal);
oHeaderStructDefinition.createElement("f64HeaderVal", &tHeaderStruct::f64HeaderVal);
auto oNestedDefinition = structure<tNestedStruct>("tNestedStruct");
oNestedDefinition.createElement("sHeaderStruct", &tNestedStruct::sHeaderStruct, oHeaderStructDefinition);
oNestedDefinition.createElement("sSimpleStruct", &tNestedStruct::sSimpleStruct, oSimpleStructDefinition);
// we create an output pin with a writer that handles creating samples for tNestedStruct transparently.
m_pWriterNested = CreateOutputPin("nested_struct", oNestedDefinition);
SetDescription("nested_struct", "Provides the generated data based on number_gen_type");
auto oNestedArrayDefinition = structure<tNestedArrayStruct>("tNestedArrayStruct");
oNestedArrayDefinition.createElement("sHeaderStructArray", &tNestedArrayStruct::sHeaderStructArray,
oHeaderStructDefinition);
oNestedArrayDefinition.createElement("sSimpleStructArray", &tNestedArrayStruct::sSimpleStructArray,
oSimpleStructDefinition);
// we create an other output pin with a writer that handles creating samples for tNestedStruct in a huge array.
m_pWriterNestedArray = CreateOutputPin("nested_struct_array", oNestedArrayDefinition);
SetDescription("nested_struct_array",
"Provides the generated data based on number_gen_type in a structure with arrays");
auto oArraysWithValidElementCountDefinition =
structure<tArraysWithValidElementCount>("tArraysWithValidElementCount");
oArraysWithValidElementCountDefinition.createElement(
"nSimpleStructArrayValidElementCount", &tArraysWithValidElementCount::nSimpleStructArrayValidElementCount);
oArraysWithValidElementCountDefinition
.createElement("sSimpleStructArray", &tArraysWithValidElementCount::sSimpleStructArray,
oSimpleStructArrayDefinition)
.setValidElementCount("nSimpleStructArrayValidElementCount");
oArraysWithValidElementCountDefinition
.createElement("nArrayValidElementCount", &tArraysWithValidElementCount::nArrayValidElementCount)
.setComment("This is an valid element count for the nArray!");
oArraysWithValidElementCountDefinition.createElement("nArray", &tArraysWithValidElementCount::nArray,
"nArrayValidElementCount");
// valid element count and valid bool elements are allowed to exists after the value it is for:
oArraysWithValidElementCountDefinition.createElement("nValue", &tArraysWithValidElementCount::nValue);
oArraysWithValidElementCountDefinition.createElement("bValueValid", &tArraysWithValidElementCount::bValueValid);
oArraysWithValidElementCountDefinition.getElement("nValue").setValidElementCount("bValueValid");
// we create an other output pin with a writer that handles creating samples for tArraysWithValidElementCount.
m_pWriterArraysWithValidElementCount =
CreateOutputPin("arrays_with_valid_element_count", oArraysWithValidElementCountDefinition);
SetDescription("arrays_with_valid_element_count", "Provides the generated data based on number_gen_type in a "
"struct containing arrays with valid element count set");
// create a trigger function that can be connected to an active runner.
CreateRunner("data_generator_function", cTimerTriggerHint(std::chrono::seconds{1}));
SetDescription("data_generator_function",
"Runner to periodically trigger the function which generates the output data for all pins");
// setup and register our property variable which will reflect any property change.
// for compatibility with previous implementations we use the "data_generator_function" prefix.
m_eGeneratorType.SetValueList({{eCounter, "Counter"}, {eRandom, "Random"}});
m_eGeneratorType.SetDescription("Chooses the generator used for calculating output data.");
RegisterPropertyVariable("data_generator_function/number_gen_type", m_eGeneratorType);
// sets a short description for the component
SetDescription("Use this filter to generate data whenever a defined Timer Runner triggers.");
// set help link to jump to documentation from ADTF Configuration Editor
SetHelpLink("$(ADTF_DIR)/doc/html/page_demo_time_trigger.html");
}
cSimpleDataGenerator::~cSimpleDataGenerator() = default;
// in this method all property related and/or long running initialization can be done.
tResult cSimpleDataGenerator::Init(tInitStage eStage)
{
RETURN_IF_FAILED(cFilter::Init(eStage));
if (eStage == StageNormal)
{
switch (m_eGeneratorType)
{
case eCounter:
{
m_fnGenerator = [&]
{
return static_cast<double>(++m_nCounter);
};
LOG_INFO("Current generation type is Counter");
break;
}
case eRandom:
{
m_fnGenerator = [&]
{
return m_oDistribution(m_oRandomGenerator);
};
LOG_INFO("Current generation type is Random");
break;
}
default:
{
RETURN_ERROR_DESC(ERR_INVALID_ARG,
"Invalid property value '%" PRIu32 "' for 'number_gen_type', use Counter",
*m_eGeneratorType);
}
}
}
}
// this function will be executed each time a trigger occured
tResult cSimpleDataGenerator::Process(tNanoSeconds tmTimeOfTrigger, IRunner* /*pRunner*/)
{
double fOutValue = m_fnGenerator();
GenerateSimpleData(tmTimeOfTrigger, fOutValue);
GenerateSimpleArrayData(tmTimeOfTrigger, fOutValue);
GenerateNestedData(tmTimeOfTrigger, fOutValue);
GenerateNestedArrayData(tmTimeOfTrigger, fOutValue);
GenerateArraysWithValidElementCountData(tmTimeOfTrigger, fOutValue);
}
void cSimpleDataGenerator::GenerateSimpleData(tNanoSeconds tmTimeOfTrigger, double fOutValue)
{
// we want to be able to profile this specific function
EASY_FUNCTION();
output_sample_data<float> oOutputData(tmTimeOfTrigger);
oOutputData = static_cast<float>(fOutValue);
m_pWriterSimple->Write(oOutputData.Release());
}
void cSimpleDataGenerator::GenerateSimpleArrayData(tNanoSeconds tmTimeOfTrigger, double fOutValue)
{
// we want to be able to profile this specific function
EASY_FUNCTION();
output_sample_data<std::array<int64_t, 10>> oOutputData(tmTimeOfTrigger);
for (auto& oCurrentArrayValue : *oOutputData)
{
oCurrentArrayValue = static_cast<int64_t>(fOutValue);
}
m_pWriterSimpleArray->Write(oOutputData.Release());
}
namespace
{
void fill_simple_struct(tSimpleStruct& oStruct, double fValue)
{
oStruct.ui8Val = static_cast<uint8_t>(fValue);
oStruct.ui16Val = static_cast<uint16_t>(fValue);
oStruct.ui32Val = static_cast<uint32_t>(fValue);
oStruct.i32Val = static_cast<int32_t>(fValue);
oStruct.i64Val = static_cast<int64_t>(fValue);
oStruct.f64Val = fValue;
oStruct.f32Val = static_cast<float>(fValue);
oStruct.ei8EnumVal = static_cast<eSimpleEnum>(oStruct.ui8Val % 10);
}
void fill_header_struct(tHeaderStruct& oStruct, double fValue)
{
oStruct.ui32HeaderVal = static_cast<uint32_t>(fValue);
oStruct.f64HeaderVal = fValue;
}
} // namespace
void cSimpleDataGenerator::GenerateNestedData(tNanoSeconds tmTimeOfTrigger, double fOutValue)
{
// we want to be able to profile this specific function
EASY_FUNCTION();
output_sample_data<tNestedStruct> oOutputData(tmTimeOfTrigger);
fill_header_struct(oOutputData->sHeaderStruct, fOutValue);
fill_simple_struct(oOutputData->sSimpleStruct, fOutValue);
m_pWriterNested->Write(oOutputData.Release());
}
void cSimpleDataGenerator::GenerateNestedArrayData(tNanoSeconds tmTimeOfTrigger, double fOutValue)
{
// we want to be able to profile this specific function
EASY_FUNCTION();
output_sample_data<tNestedArrayStruct> oOutputData(tmTimeOfTrigger);
for (size_t nCurrentPos = 0; nCurrentPos < 100; ++nCurrentPos)
{
fill_header_struct(oOutputData->sHeaderStructArray[nCurrentPos], fOutValue);
}
for (size_t nCurrentPos = 0; nCurrentPos < 2000; ++nCurrentPos)
{
fill_simple_struct(oOutputData->sSimpleStructArray[nCurrentPos], fOutValue);
}
m_pWriterNestedArray->Write(oOutputData.Release());
}
void cSimpleDataGenerator::GenerateArraysWithValidElementCountData(tNanoSeconds tmTimeOfTrigger, double fOutValue)
{
// we want to be able to profile this specific function
EASY_FUNCTION();
const auto bValid = (m_nValidElementCountCounter % 20) < 10;
// fill array of structs with array of structs and valid element count
const uint32_t nSimpleArrayValidElementCount = bValid ? 10 : 20;
oOutputData->nSimpleStructArrayValidElementCount = nSimpleArrayValidElementCount;
for (uint32_t nCurrentSimpleArrayIndex = 0; nCurrentSimpleArrayIndex < nSimpleArrayValidElementCount;
++nCurrentSimpleArrayIndex)
{
auto& sCurrentStructArray = oOutputData->sSimpleStructArray[nCurrentSimpleArrayIndex];
const int32_t nSimpleValidElementCount = m_nValidElementCountCounter % 10;
sCurrentStructArray.i32SimpleValidElementCount = nSimpleValidElementCount;
for (int32_t nCurrentSimpleIndex = 0; nCurrentSimpleIndex < nSimpleValidElementCount; ++nCurrentSimpleIndex)
{
fill_simple_struct(sCurrentStructArray.sSimple[nCurrentSimpleIndex], fOutValue);
}
}
// fill array with valid element count
const uint64_t nArrayValidElementCount = bValid ? 15 : 30;
oOutputData->nArrayValidElementCount = nArrayValidElementCount;
for (uint64_t nArrayIndex = 0; nArrayIndex < nArrayValidElementCount; ++nArrayIndex)
{
oOutputData->nArray[nArrayIndex] = static_cast<int64_t>(fOutValue);
}
// fill valid flag and value
oOutputData->bValueValid = bValid;
oOutputData->nValue = static_cast<int64_t>(fOutValue);
m_pWriterArraysWithValidElementCount->Write(oOutputData.Release());
++m_nValidElementCountCounter;
}
#define ADTF_PLUGIN(__plugin_identifier,...)
Definition adtf_plugin.h:29
#define LOG_INFO(...)
Logs an info message.
Definition log.h:388
#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
Definition type_reflection.h:51
enumeration & Add(const std::string &strName, Type eValue)
Definition type_reflection.h:86
Definition type_reflection.h:124
Generator template to create an instance of a ant::IStreamType class for penguin::stream_meta_type_pl...
Definition streammetatypeplain.h:315
Namespace for the ADTF Base SDK.
Definition adtf_base_type_traits.h:13
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
Namespace for the ADTF uCOM SDK.
Definition adtf_system.h:324
definition of the ddl namespace
Definition codec.h:21