ADTF  3.18.3
Source Code for Demo Virtual Clock Input Plugin
Location
./src/examples/src/adtf/streaming_services/sources/virtual_clock/
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:
Header
#pragma once
using namespace adtf::base;
using namespace adtf::ucom;
using namespace adtf::streaming;
using namespace adtf::filter;
using namespace adtf::system;
//*************************************************************************************************
class cDemoVirtualClock : public adtf::filter::cSampleStreamingSource
{
public:
ADTF_CLASS_ID_NAME(cDemoVirtualClock,
"demo_virtual_clock_input.streaming_source.adtf.cid",
"Demo Virtual Clock");
private:
ISampleWriter* m_pWriter = nullptr;
property_variable<uint32_t> m_nWidth = 640;
property_variable<uint32_t> m_nHeight = 480;
property_variable<int64_t> m_nFrameDelay = 100000;
object_ptr<adtf::services::IReferenceClock> m_pClock;
public:
cDemoVirtualClock();
tResult Init() override;
tResult StartStreaming() override;
tResult StopStreaming() override;
private:
object_ptr<IStreamType> GetStreamTypeFromProperties();
void TimerFunc();
object_ptr<ISample> CreateNewFrame(tNanoSeconds tmNow);
void DrawCircle(void* pvBuffer, int nLineWidth);
void DrawPixel(void* pvBuffer, int nLineWidth, int x, int y, int nValue);
void DrawLine(void* pvBuffer, int nLineWidth, int x0, int y0, int x1, int y1);
void DrawTimeLines(void* pvBuffer, tNanoSeconds tmTime);
void DrawTimeLine(void* pvBuffer,
int nLineWidth,
int nClockTime,
int nPrecision);
void DrawClock(void* pvBuffer, tNanoSeconds tmNow);
};
Copyright © Audi Electronics Venture GmbH.
Copyright © Audi Electronics Venture GmbH.
#define REQUIRE_INTERFACE(_interface)
Macro usable with ADTF_CLASS_DEPENDENCIES() to require mandatory interfaces.
#define ADTF_CLASS_DEPENDENCIES(...)
Add interface ids (string literals,.
#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
Base class for ADTF sample streaming sources.
This class is used to provide a fallback kernel thread/timer for a runner of a streaming service.
Kernel interface for thread, timer and signal handling.
Definition: kernel_intf.h:388
The IReferenceClock interface provides the reference time source for the filter graph.
Namespace for the ADTF Base SDK.
Namespace for the ADTF Filter SDK.
Namespace for the ADTF Streaming SDK.
Namespace for the ADTF System SDK.
Namespace for the ADTF uCOM3 SDK.
Copyright © Audi Electronics Venture GmbH.
Implementation
#include "demo_virtual_clock.h"
#include <cmath>
ADTF_PLUGIN("Demo Virtual Clock Plugin",
cDemoVirtualClock);
cDemoVirtualClock::cDemoVirtualClock()
{
m_nWidth.SetDescription("Specified width for Sample dimension.");
RegisterPropertyVariable("width", m_nWidth);
m_nHeight.SetDescription("Specified height for Sample dimension.");
RegisterPropertyVariable("height", m_nHeight);
m_nFrameDelay.SetDescription("Update interval in microseconds for Sample creation. This is only used when no Timer Runner is connected to the 'generate_frames' runner.");
RegisterPropertyVariable("frame_delay", m_nFrameDelay);
m_pWriter = CreateOutputPin("outpin", GetStreamTypeFromProperties());
SetDescription("outpin", "Provides the generated clock video samples");
// For session compatibility reasons we use this fallback helper for the case where no active runner is connected to the runner.
// In your own implementations use a simple CreateRunner(...) instead!
m_oTimer = adtf::filter::cRunnerFallback(this, "generate_frames", cTimerTriggerHint(*m_nFrameDelay), [this]{ TimerFunc(); });
SetDescription("generate_frames",
"Connect a Timer Runner that will trigger the frame generation. In this case the property `frame_delay` has no effect."
"If this is not connected, the source will create a timer on its own.");
// sets a short description for the component
SetDescription("Use this Streaming Source to generate video data configured by 'width', 'height' and 'frame_delay properties.");
// set help link to jump to documentation from ADTF Configuration Editor
SetHelpLink("$(ADTF_DIR)/doc/adtf_html/page_demo_virtual_clock.html");
}
tResult cDemoVirtualClock::Init()
{
RETURN_IF_FAILED(cSampleStreamingSource::Init());
m_pWriter->ChangeType(GetStreamTypeFromProperties());
}
object_ptr<IStreamType> cDemoVirtualClock::GetStreamTypeFromProperties()
{
tStreamImageFormat sFormat;
sFormat.m_strFormatName = ADTF_IMAGE_FORMAT(GREYSCALE_8);
sFormat.m_ui32Width = m_nWidth;
sFormat.m_ui32Height = m_nHeight;
sFormat.m_szMaxByteSize = m_nWidth * m_nHeight;
sFormat.m_ui8DataEndianess = PLATFORM_BYTEORDER;
object_ptr<IStreamType> pType = make_object_ptr<cStreamType>(stream_meta_type_image());
set_stream_type_image_format(*pType, sFormat);
return pType;
}
tResult cDemoVirtualClock::StartStreaming()
{
RETURN_IF_FAILED(cSampleStreamingSource::StartStreaming());
RETURN_IF_FAILED(m_oTimer.Activate(m_nFrameDelay));
}
tResult cDemoVirtualClock::StopStreaming()
{
m_oTimer.Deactivate();
return cSampleStreamingSource::StopStreaming();
}
void cDemoVirtualClock::TimerFunc()
{
auto tmNow = m_pClock->GetStreamTimeNs();
object_ptr<const ISample> pSample = CreateNewFrame(tmNow);
if (!pSample)
{
m_pWriter->SetStreamError(ERR_BAD_DEVICE);
return;
}
m_pWriter->Write(pSample);
m_pWriter->ManualTrigger(tmNow);
}
object_ptr<ISample> cDemoVirtualClock::CreateNewFrame(tNanoSeconds tmNow)
{
object_ptr<ISample> pSample;
if (IS_OK(alloc_sample(pSample, tmNow)))
{
object_ptr_locked<ISampleBuffer> pBuffer;
if (IS_OK(pSample->WriteLock(pBuffer, m_nWidth * m_nHeight)))
{
DrawClock(pBuffer->GetPtr(), tmNow);
}
}
return pSample;
}
void cDemoVirtualClock::DrawClock(void* pvBuffer, tNanoSeconds tmNow)
{
// generate black image
adtf_util::cMemoryBlock::MemZero(pvBuffer, m_nWidth * m_nHeight);
int x2 = m_nWidth / 2;
int y2 = m_nHeight / 2;
int Radius = (x2 < y2) ? x2 : y2;
DrawCircle(pvBuffer, 2);
DrawLine(pvBuffer, 1, 0, Radius, Radius/5, Radius);
DrawLine(pvBuffer, 1, 2*Radius - Radius/5, Radius, Radius*2, Radius);
DrawLine(pvBuffer, 1, Radius , 0, Radius, Radius/5);
DrawLine(pvBuffer, 1, Radius , 2*Radius, Radius, 2*Radius - Radius/5);
DrawTimeLines(pvBuffer, tmNow);
}
void cDemoVirtualClock::DrawTimeLine(void* pvBuffer,
int nLineWidth,
int nClockTime,
int nPrecision)
{
int x2 = m_nWidth / 2;
int y2 = m_nHeight / 2;
int nRadius = (x2 < y2) ? x2 : y2;
if (nPrecision == 0) return;
int nRest = nClockTime % nPrecision;
double alpha = double( 360.0 / nPrecision) * double(nRest);
int x = int(sin((alpha / 180.0) * 3.145) * double(nRadius));
int y = int(cos((alpha / 180.0) * 3.145) * double(nRadius));
if (nRest >= 0 && nRest <= nPrecision/2)
{
if (x < 0)
{
x = nRadius - x;
}
else
{
x = nRadius + x;
}
}
else
{
if (x < 0)
{
x = nRadius + x;
}
else
{
x = nRadius - x;
}
}
if (nRest >= nPrecision/4 && nRest <= (nPrecision*3)/4)
{
if (y < 0)
{
y = nRadius - y;
}
else
{
y = nRadius + y;
}
}
else
{
if (y < 0)
{
y = nRadius + y;
}
else
{
y = nRadius - y;
}
}
DrawLine(pvBuffer, nLineWidth, nRadius, nRadius, x, y);
}
void cDemoVirtualClock::DrawTimeLines(void* pvBuffer, tNanoSeconds tmTime)
{
int nSeconds = int(tmTime / std::chrono::seconds(1));
int nMinutes = nSeconds * 2000 / 60;
DrawTimeLine(pvBuffer, 1, nSeconds, 60);
DrawTimeLine(pvBuffer, 2, nMinutes, 2000 * 60);
}
void cDemoVirtualClock::DrawCircle(void* pvBuffer, int nLineWidth)
{
//simple algorithm from bresenham
int x2 = m_nWidth / 2;
int y2 = m_nHeight / 2;
int Radius = (x2 < y2) ? x2 : y2;
Radius = Radius - nLineWidth;
int x = 0;
int y = Radius;
int S = 0;
int xBreakPixel = int(double(3.1) * double(Radius) / double(4.0));
while (x < xBreakPixel )
{
DrawPixel(pvBuffer, nLineWidth, x + Radius, Radius - y, 0xFF);
DrawPixel(pvBuffer, nLineWidth, Radius - x, Radius - y, 0xFF);
DrawPixel(pvBuffer, nLineWidth, Radius + y, Radius - x, 0xFF);
DrawPixel(pvBuffer, nLineWidth, Radius - y, Radius - x, 0xFF);
DrawPixel(pvBuffer, nLineWidth, Radius + y, Radius + x, 0xFF);
DrawPixel(pvBuffer, nLineWidth, Radius - y, Radius + x, 0xFF);
DrawPixel(pvBuffer, nLineWidth, x + Radius, Radius + y, 0xFF);
DrawPixel(pvBuffer, nLineWidth, Radius - x, Radius + y, 0xFF);
int qRadius = Radius * Radius;
int qx = (x + 1) * (x + 1);
S = qx + (y * y) - qRadius;
S += (qx + ((y - 1) * (y - 1)) - qRadius);
x++;
if (S > 0)
{
y--;
}
}
}
void cDemoVirtualClock::DrawPixel(void* pvBuffer, int nLineWidth,
int xWidth , int yHeight , int nValue)
{
uint8_t* pImage = (uint8_t*)pvBuffer;
if (xWidth >= 0 && xWidth < static_cast<int>(m_nWidth)
&& yHeight >= 0 && yHeight < static_cast<int>(m_nHeight))
{
int nPixelNo = (yHeight * static_cast<int>(m_nWidth)) + xWidth;
if (nPixelNo > 0 && nPixelNo < static_cast<int>(m_nWidth) * static_cast<int>(m_nHeight))
{
pImage[nPixelNo] = (uint8_t)nValue;
if (nLineWidth > 1)
{
for (int nIdx = 1; nIdx <= nLineWidth/2; nIdx++)
{
DrawPixel(pvBuffer, nLineWidth/2-1, xWidth+nIdx, yHeight, nValue);
DrawPixel(pvBuffer, nLineWidth/2-1, xWidth, yHeight+nIdx, nValue);
}
for (int nIdx = nLineWidth; nIdx > 1; nIdx--)
{
DrawPixel(pvBuffer, nLineWidth/2-1, xWidth+nIdx, yHeight, nValue);
DrawPixel(pvBuffer, nLineWidth/2-1, xWidth, yHeight+nIdx, nValue);
}
}
}
}
}
void cDemoVirtualClock::DrawLine(void* pvBuffer,
int nLineWidth,
int x0Width,
int y0Height,
int x1Width,
int y1Height)
{
int x0 = x0Width;
int y0 = y0Height;
int x1 = x1Width;
int y1 = y1Height;
int deltax = abs(x1 - x0);
int deltay = abs(y1 - y0);
bool bSwapped = false;
if (deltay > deltax)
{
bSwapped = true;
x0 = y0Height;
x1 = y1Height;
y0 = x0Width;
y1 = x1Width;
}
if (x0 > x1)
{
int nSwap = 0;
nSwap = x1;
x1 = x0;
x0 = nSwap;
nSwap = y1;
y1 = y0;
y0 = nSwap;
}
deltax = x1 - x0;
deltay = abs(y1 - y0);
int delta = -deltax / 2;
int x = x0;
int y = y0;
for (; x <= x1; x++)
{
if (bSwapped)
{
DrawPixel(pvBuffer, nLineWidth, y, x, 0xFF);
}
else
{
DrawPixel(pvBuffer, nLineWidth, x, y, 0xFF);
}
delta = delta + deltay;
if (delta > 0)
{
if (y0 < y1)
{
y++;
}
else
{
y--;
}
delta = delta - deltax;
}
}
}
#define ADTF_PLUGIN(__plugin_identifier,...)
The ADTF Plugin Macro will add the code of a adtf::ucom::ant::IPlugin implementation.
Definition: adtf_plugin.h:22
#define RETURN_IF_FAILED(s)
Return if expression is failed, which requires the calling function's return type to be tResult.
#define RETURN_NOERROR
Return status ERR_NOERROR, which requires the calling function's return type to be tResult.
virtual tResult GetObject(iobject_ptr< IObject > &pObject, const char *strNameOID) const =0
Get registered object from object registry.
#define PLATFORM_BYTEORDER
defines a link to __get_platform_byteorder.
Definition: constants.h:124
tResult set_stream_type_image_format(IStreamType &oType, const tStreamImageFormat &oFormat)
Helper function to set the properties of a IStreamType for a stream_meta_type_image.
tResult alloc_sample(ucom::ant::iobject_ptr< ucom::ant::IObject > &pSampleObject, const char *strSampleCID)
Helper Function to get a Sample Instance through the adtf::ucom::ant::IRuntime.
adtf::ucom::IRuntime * _runtime
Global Runtime Pointer to reference to the current runtime.
#define ADTF_IMAGE_FORMAT(_FORMAT_)
Helper Macro to get the FormatName of the predefined Format within stream_image_format.