#include "demo_virtual_clock.h"
#include <cmath>
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");
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.");
SetDescription("Use this Streaming Source to generate video data configured by 'width', 'height' and 'frame_delay properties.");
SetHelpLink("$(ADTF_DIR)/doc/adtf_html/page_demo_virtual_clock.html");
}
{
m_pWriter->ChangeType(GetStreamTypeFromProperties());
}
object_ptr<IStreamType> cDemoVirtualClock::GetStreamTypeFromProperties()
{
tStreamImageFormat sFormat;
sFormat.m_ui32Width = m_nWidth;
sFormat.m_ui32Height = m_nHeight;
sFormat.m_szMaxByteSize = m_nWidth * m_nHeight;
object_ptr<IStreamType> pType = make_object_ptr<cStreamType>(stream_meta_type_image());
return pType;
}
tResult cDemoVirtualClock::StartStreaming()
{
}
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;
{
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)
{
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 nMinutes = nSeconds * 2000 / 60;
DrawTimeLine(pvBuffer, 1, nSeconds, 60);
DrawTimeLine(pvBuffer, 2, nMinutes, 2000 * 60);
}
void cDemoVirtualClock::DrawCircle(void* pvBuffer, int nLineWidth)
{
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.
#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.
#define IS_OK(s)
Check if result is OK.
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.
std::chrono::seconds seconds
Compatibility to C++11 std::chrono::seconds
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.