ADTF
Loading...
Searching...
No Matches
Example Demo Virtual Clock

Description

Shows how to create samples containing images.

Prebuilt Binaries

Source Code

./examples/demo_adtfplugins/demo_virtual_clock/

Streaming Source

demo_virtual_clock.h

#pragma once
#ifndef ADTF_EXAMPLES_CID
#define ADTF_EXAMPLES_CID ".local.cid"
#endif
//*************************************************************************************************
class cDemoVirtualClock final : public adtf::filter::cSampleStreamingSource
{
public:
ADTF_CLASS_ID_NAME(cDemoVirtualClock,
"demo_virtual_clock_input.streaming_source" ADTF_EXAMPLES_CID,
"Demo Virtual Clock");
private:
adtf::streaming::ISampleWriter* m_pWriter = nullptr;
public:
cDemoVirtualClock();
~cDemoVirtualClock() override;
tResult Init() override;
tResult StartStreaming() override;
tResult StopStreaming() override;
private:
void TimerFunc();
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, adtf::base::tNanoSeconds tmTime);
void DrawTimeLine(void* pvBuffer,
int nLineWidth,
int nClockTime,
int nPrecision);
void DrawClock(void* pvBuffer, adtf::base::tNanoSeconds tmNow);
};
A_UTILS_NS::cResult tResult
For backwards compatibility and to bring latest version into scope.
Definition result.h:736
#define REQUIRE_INTERFACE(_interface)
Macro usable with ADTF_CLASS_DEPENDENCIES() to require mandatory interfaces.
Definition class_dependencies.h:36
#define ADTF_CLASS_DEPENDENCIES(...)
Add interface ids (string literals,.
Definition class_dependencies.h:61
#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 sample_streaming_source.h:50
Definition runner_fallback.h:25
Definition kernel_intf.h:390
Definition reference_clock_intf.h:782
Definition samplestreamer_intf.h:234
Definition object_ptr.h:384
A timestamp with nanosecond precision.
Definition chrono.h:23

demo_virtual_clock.cpp

#include "demo_virtual_clock.h"
#include <cmath>
using namespace adtf::base;
using namespace adtf::ucom;
using namespace adtf::streaming;
using namespace adtf::filter;
using namespace adtf::system;
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/html/page_demo_virtual_clock.html");
}
cDemoVirtualClock::~cDemoVirtualClock() = default;
tResult cDemoVirtualClock::Init()
{
RETURN_IF_FAILED(cSampleStreamingSource::Init());
m_pWriter->ChangeType(GetStreamTypeFromProperties());
}
object_ptr<IStreamType> cDemoVirtualClock::GetStreamTypeFromProperties()
{
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;
set_stream_type_image_format(*pType, sFormat);
return pType;
}
tResult cDemoVirtualClock::StartStreaming()
{
RETURN_IF_FAILED(_runtime->GetObject(m_pClock));
RETURN_IF_FAILED(m_oTimer.Activate(m_nFrameDelay));
}
tResult cDemoVirtualClock::StopStreaming()
{
m_oTimer.Deactivate();
}
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)
{
if (IS_OK(alloc_sample(pSample, tmNow)))
{
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,...)
Definition adtf_plugin.h:29
#define RETURN_NOERROR
Return status ERR_NOERROR, which requires the calling function's return type to be tResult.
Definition result.h:29
#define IS_OK(s)
Check if result is OK.
Definition result.h:17
Definition lockedobject_intf.h:207
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 Streaming SDK.
Definition bindingproxyinport.h:14
tResult alloc_sample(ucom::ant::iobject_ptr< ucom::ant::IObject > &pSample)
tResult set_stream_type_image_format(IStreamType &oType, const tStreamImageFormat &oFormat)
Namespace for the ADTF System SDK.
Definition adtf_service.h:14
Namespace for the ADTF uCOM SDK.
Definition adtf_system.h:324
object_ptr< Implementation > make_object_ptr(Args &&... args)
Alias always bringing the latest version of ant::make_object_ptr() into scope.
Definition object_ptr_utilities.h:129
#define ADTF_IMAGE_FORMAT(_FORMAT_)
Definition streamimageformat.h:183
Definition streamimageformat.h:30
tStreamImageFormatName m_strFormatName
Formatname of the image - see adtf::streaming::ant::imageformat_definition. usually it is a pixelform...
Definition streamimageformat.h:33
uint32_t m_ui32Width
Pixel width of the image.
Definition streamimageformat.h:35
size_t m_szMaxByteSize
Maximal byte size of the image.
Definition streamimageformat.h:39
uint32_t m_ui32Height
Pixel height of the image.
Definition streamimageformat.h:37
uint8_t m_ui8DataEndianess
Endianess of the image (usually pixel endianess) - by default this is PLATFORM_BYTEORDER (PLATFORM_BI...
Definition streamimageformat.h:43
Use this Stream Meta Type for describing a video stream with single frames and there format and set t...
Definition streammetatypeimage.h:101