This commit is contained in:
2021-10-14 13:47:35 +02:00
commit 6625a8dfaa
4026 changed files with 844291 additions and 0 deletions
@@ -0,0 +1,36 @@
PROJECT(openvibe-plugins-sdk-streaming)
SET(PROJECT_VERSION_MAJOR ${OV_GLOBAL_VERSION_MAJOR})
SET(PROJECT_VERSION_MINOR ${OV_GLOBAL_VERSION_MINOR})
SET(PROJECT_VERSION_PATCH ${OV_GLOBAL_VERSION_PATCH})
SET(PROJECT_VERSION ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH})
FILE(GLOB_RECURSE SRC_FILES src/*.cpp src/*.h src/*.hpp src/*.inl)
INCLUDE("FindSourceRCProperties")
ADD_LIBRARY(${PROJECT_NAME} SHARED ${SRC_FILES})
SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES
VERSION ${PROJECT_VERSION}
SOVERSION ${PROJECT_VERSION_MAJOR}
FOLDER ${PLUGINS_FOLDER}
COMPILE_FLAGS "-DOVP_Exports -DOVP_Shared")
# ---------------------------------
INCLUDE("FindOpenViBE")
INCLUDE("FindOpenViBECommon")
INCLUDE("FindOpenViBEToolkit")
# ---------------------------------
# Target macros
# Defines target operating system, architecture and compiler
# ---------------------------------
SET_BUILD_PLATFORM()
# -----------------------------
# Install files
# -----------------------------
INSTALL(TARGETS ${PROJECT_NAME}
RUNTIME DESTINATION ${DIST_BINDIR}
LIBRARY DESTINATION ${DIST_LIBDIR}
ARCHIVE DESTINATION ${DIST_LIBDIR})
INSTALL(DIRECTORY box-tutorials DESTINATION ${DIST_DATADIR}/openvibe/scenarios/)
@@ -0,0 +1,315 @@
<OpenViBE-Scenario>
<FormatVersion>1</FormatVersion>
<Creator>OpenVIBE</Creator>
<CreatorVersion>0.0.0</CreatorVersion>
<Settings></Settings>
<Inputs></Inputs>
<Outputs></Outputs>
<Boxes>
<Box>
<Identifier>(0x00000d77, 0x0000139e)</Identifier>
<Name>Signal Merger</Name>
<AlgorithmClassIdentifier>(0x4bf9326f, 0x75603102)</AlgorithmClassIdentifier>
<Inputs>
<Input>
<TypeIdentifier>(0x5ba36127, 0x195feae1)</TypeIdentifier>
<Name>Input 1</Name>
</Input>
<Input>
<TypeIdentifier>(0x5ba36127, 0x195feae1)</TypeIdentifier>
<Name>Input 2</Name>
</Input>
</Inputs>
<Outputs>
<Output>
<TypeIdentifier>(0x5ba36127, 0x195feae1)</TypeIdentifier>
<Name>Merged</Name>
</Output>
</Outputs>
<Attributes>
<Attribute>
<Identifier>(0x1fa7a38f, 0x54edbe0b)</Identifier>
<Value>256</Value>
</Attribute>
<Attribute>
<Identifier>(0x207c9054, 0x3c841b63)</Identifier>
<Value>240</Value>
</Attribute>
<Attribute>
<Identifier>(0x4e7b798a, 0x183beafb)</Identifier>
<Value>(0x990c5a68, 0x0d4024a3)</Value>
</Attribute>
<Attribute>
<Identifier>(0xc67a01dc, 0x28ce06c1)</Identifier>
<Value></Value>
</Attribute>
<Attribute>
<Identifier>(0xc80ce8af, 0xf699f813)</Identifier>
<Value>1</Value>
</Attribute>
<Attribute>
<Identifier>(0xcfad85b0, 0x7c6d841c)</Identifier>
<Value>2</Value>
</Attribute>
<Attribute>
<Identifier>(0xfba64161, 0x65304e21)</Identifier>
<Value></Value>
</Attribute>
</Attributes>
</Box>
<Box>
<Identifier>(0x0000476b, 0x0000666f)</Identifier>
<Name>Time signal</Name>
<AlgorithmClassIdentifier>(0x28a5e7ff, 0x530095de)</AlgorithmClassIdentifier>
<Outputs>
<Output>
<TypeIdentifier>(0x5ba36127, 0x195feae1)</TypeIdentifier>
<Name>Generated signal</Name>
</Output>
</Outputs>
<Settings>
<Setting>
<TypeIdentifier>(0x007deef9, 0x2f3e95c6)</TypeIdentifier>
<Name>Sampling frequency</Name>
<DefaultValue>512</DefaultValue>
<Value>512</Value>
<Modifiability>false</Modifiability>
</Setting>
<Setting>
<TypeIdentifier>(0x007deef9, 0x2f3e95c6)</TypeIdentifier>
<Name>Generated epoch sample count</Name>
<DefaultValue>32</DefaultValue>
<Value>32</Value>
<Modifiability>false</Modifiability>
</Setting>
</Settings>
<Attributes>
<Attribute>
<Identifier>(0x1fa7a38f, 0x54edbe0b)</Identifier>
<Value>112</Value>
</Attribute>
<Attribute>
<Identifier>(0x207c9054, 0x3c841b63)</Identifier>
<Value>336</Value>
</Attribute>
<Attribute>
<Identifier>(0x4e7b798a, 0x183beafb)</Identifier>
<Value>(0x9e5ca01e, 0x30a4d8c3)</Value>
</Attribute>
<Attribute>
<Identifier>(0xc80ce8af, 0xf699f813)</Identifier>
<Value>1</Value>
</Attribute>
<Attribute>
<Identifier>(0xce18836a, 0x9c0eb403)</Identifier>
<Value>2</Value>
</Attribute>
</Attributes>
</Box>
<Box>
<Identifier>(0x00004baf, 0x0000758e)</Identifier>
<Name>Continuous Oscilloscope</Name>
<AlgorithmClassIdentifier>(0x0842bcd1, 0xd53c1c89)</AlgorithmClassIdentifier>
<Inputs>
<Input>
<TypeIdentifier>(0x5ba36127, 0x195feae1)</TypeIdentifier>
<Name>Matrix</Name>
</Input>
<Input>
<TypeIdentifier>(0x6f752dd0, 0x082a321e)</TypeIdentifier>
<Name>Markers</Name>
</Input>
</Inputs>
<Settings>
<Setting>
<TypeIdentifier>(0x330306dd, 0x74a95f98)</TypeIdentifier>
<Name>Channel Localisation</Name>
<DefaultValue>${AdvancedViz_ChannelLocalisation}</DefaultValue>
<Value>${AdvancedViz_ChannelLocalisation}</Value>
<Modifiability>false</Modifiability>
</Setting>
<Setting>
<TypeIdentifier>(0x8f02e3f6, 0xffb00f4b)</TypeIdentifier>
<Name>Temporal Coherence</Name>
<DefaultValue>Time Locked</DefaultValue>
<Value>Time Locked</Value>
<Modifiability>false</Modifiability>
</Setting>
<Setting>
<TypeIdentifier>(0x512a166f, 0x5c3ef83f)</TypeIdentifier>
<Name>Time Scale</Name>
<DefaultValue>20</DefaultValue>
<Value>20</Value>
<Modifiability>false</Modifiability>
</Setting>
<Setting>
<TypeIdentifier>(0x007deef9, 0x2f3e95c6)</TypeIdentifier>
<Name>Matrix Count</Name>
<DefaultValue>50</DefaultValue>
<Value>50</Value>
<Modifiability>false</Modifiability>
</Setting>
<Setting>
<TypeIdentifier>(0x2cdb2f0b, 0x12f231ea)</TypeIdentifier>
<Name>Positive Data Only ?</Name>
<DefaultValue>false</DefaultValue>
<Value>false</Value>
<Modifiability>false</Modifiability>
</Setting>
<Setting>
<TypeIdentifier>(0x512a166f, 0x5c3ef83f)</TypeIdentifier>
<Name>Gain</Name>
<DefaultValue>1</DefaultValue>
<Value>1</Value>
<Modifiability>false</Modifiability>
</Setting>
<Setting>
<TypeIdentifier>(0x79a9edeb, 0x245d83fc)</TypeIdentifier>
<Name>Caption</Name>
<DefaultValue></DefaultValue>
<Value></Value>
<Modifiability>false</Modifiability>
</Setting>
<Setting>
<TypeIdentifier>(0x512a166f, 0x5c3ef83f)</TypeIdentifier>
<Name>Translucency</Name>
<DefaultValue>1</DefaultValue>
<Value>1</Value>
<Modifiability>false</Modifiability>
</Setting>
<Setting>
<TypeIdentifier>(0x7f45a2a9, 0x7db12219)</TypeIdentifier>
<Name>Color</Name>
<DefaultValue>${AdvancedViz_DefaultColor}</DefaultValue>
<Value>${AdvancedViz_DefaultColor}</Value>
<Modifiability>false</Modifiability>
</Setting>
</Settings>
<Attributes>
<Attribute>
<Identifier>(0x1fa7a38f, 0x54edbe0b)</Identifier>
<Value>352</Value>
</Attribute>
<Attribute>
<Identifier>(0x207c9054, 0x3c841b63)</Identifier>
<Value>240</Value>
</Attribute>
<Attribute>
<Identifier>(0x4e7b798a, 0x183beafb)</Identifier>
<Value>(0x35390ab5, 0x7b926078)</Value>
</Attribute>
<Attribute>
<Identifier>(0x527ad68d, 0x16d746a0)</Identifier>
<Value></Value>
</Attribute>
<Attribute>
<Identifier>(0xce18836a, 0x9c0eb403)</Identifier>
<Value>9</Value>
</Attribute>
<Attribute>
<Identifier>(0xcfad85b0, 0x7c6d841c)</Identifier>
<Value>2</Value>
</Attribute>
</Attributes>
</Box>
<Box>
<Identifier>(0x00007293, 0x00000949)</Identifier>
<Name>Sinus oscillator</Name>
<AlgorithmClassIdentifier>(0x7e33bdb8, 0x68194a4a)</AlgorithmClassIdentifier>
<Outputs>
<Output>
<TypeIdentifier>(0x5ba36127, 0x195feae1)</TypeIdentifier>
<Name>Generated signal</Name>
</Output>
</Outputs>
<Settings>
<Setting>
<TypeIdentifier>(0x007deef9, 0x2f3e95c6)</TypeIdentifier>
<Name>Channel count</Name>
<DefaultValue>4</DefaultValue>
<Value>2</Value>
<Modifiability>false</Modifiability>
</Setting>
<Setting>
<TypeIdentifier>(0x007deef9, 0x2f3e95c6)</TypeIdentifier>
<Name>Sampling frequency</Name>
<DefaultValue>512</DefaultValue>
<Value>512</Value>
<Modifiability>false</Modifiability>
</Setting>
<Setting>
<TypeIdentifier>(0x007deef9, 0x2f3e95c6)</TypeIdentifier>
<Name>Generated epoch sample count</Name>
<DefaultValue>32</DefaultValue>
<Value>32</Value>
<Modifiability>false</Modifiability>
</Setting>
</Settings>
<Attributes>
<Attribute>
<Identifier>(0x1fa7a38f, 0x54edbe0b)</Identifier>
<Value>112</Value>
</Attribute>
<Attribute>
<Identifier>(0x207c9054, 0x3c841b63)</Identifier>
<Value>160</Value>
</Attribute>
<Attribute>
<Identifier>(0x4e7b798a, 0x183beafb)</Identifier>
<Value>(0x0b214ed8, 0x1f9ad83a)</Value>
</Attribute>
<Attribute>
<Identifier>(0xc80ce8af, 0xf699f813)</Identifier>
<Value>1</Value>
</Attribute>
<Attribute>
<Identifier>(0xce18836a, 0x9c0eb403)</Identifier>
<Value>3</Value>
</Attribute>
</Attributes>
</Box>
</Boxes>
<Links>
<Link>
<Identifier>(0x00002404, 0x00007988)</Identifier>
<Source>
<BoxIdentifier>(0x00007293, 0x00000949)</BoxIdentifier>
<BoxOutputIndex>0</BoxOutputIndex>
</Source>
<Target>
<BoxIdentifier>(0x00000d77, 0x0000139e)</BoxIdentifier>
<BoxInputIndex>0</BoxInputIndex>
</Target>
</Link>
<Link>
<Identifier>(0x00005602, 0x000039b9)</Identifier>
<Source>
<BoxIdentifier>(0x0000476b, 0x0000666f)</BoxIdentifier>
<BoxOutputIndex>0</BoxOutputIndex>
</Source>
<Target>
<BoxIdentifier>(0x00000d77, 0x0000139e)</BoxIdentifier>
<BoxInputIndex>1</BoxInputIndex>
</Target>
</Link>
<Link>
<Identifier>(0x00007f7d, 0x0000105b)</Identifier>
<Source>
<BoxIdentifier>(0x00000d77, 0x0000139e)</BoxIdentifier>
<BoxOutputIndex>0</BoxOutputIndex>
</Source>
<Target>
<BoxIdentifier>(0x00004baf, 0x0000758e)</BoxIdentifier>
<BoxInputIndex>0</BoxInputIndex>
</Target>
</Link>
</Links>
<Comments></Comments>
<Metadata>
<Entry>
<Identifier>(0x0000775c, 0x000078ff)</Identifier>
<Type>(0x3bcce5d2, 0x43f2d968)</Type>
<Data>[{"boxIdentifier":"(0x00004baf, 0x0000758e)","childCount":0,"identifier":"(0x000040b5, 0x00003ea5)","index":0,"parentIdentifier":"(0xffffffff, 0xffffffff)","type":3},{"boxIdentifier":"(0xffffffff, 0xffffffff)","childCount":1,"height":320,"identifier":"(0x00007db6, 0x00005d30)","index":0,"name":"Default window","parentIdentifier":"(0xffffffff, 0xffffffff)","type":1,"width":480},{"boxIdentifier":"(0xffffffff, 0xffffffff)","childCount":1,"identifier":"(0x000010e4, 0x00001956)","index":0,"name":"Default tab","parentIdentifier":"(0x00007db6, 0x00005d30)","type":2},{"boxIdentifier":"(0xffffffff, 0xffffffff)","childCount":0,"identifier":"(0x00004cdd, 0x00003e61)","index":0,"name":"Empty","parentIdentifier":"(0x000010e4, 0x00001956)","type":0}]</Data>
</Entry>
</Metadata>
</OpenViBE-Scenario>
@@ -0,0 +1,66 @@
/**
* \page BoxAlgorithm_SignalMerger Signal Merger
__________________________________________________________________
Detailed description
__________________________________________________________________
* |OVP_DocBegin_BoxAlgorithm_SignalMerger_Description|
* This box merges several input streams in a single output stream. For instance,
* if this box has two inputs with 8 channels each, the output will contain 16 channels.
*
* It important to note that the input streams must have the same structure. That is
* same sampling rate, same number of samples per buffer, and similar chunks dates.
*
* The output channel order is as follows :
* - n channels from input 1 (in the same order as in input 1)
* - m channels from input 2
* - ...
* - p channels from input N
*
* Such box has initially been proposed by Matthieu Goyat and Guillaume Lio but it
* has been completely reimplemented in march 2011 because of unpredictable behaviors in
* some conditions.
* |OVP_DocEnd_BoxAlgorithm_SignalMerger_Description|
__________________________________________________________________
Inputs description
__________________________________________________________________
* |OVP_DocBegin_BoxAlgorithm_SignalMerger_Inputs|
* This box can receive as many inputs as necessary.
* |OVP_DocEnd_BoxAlgorithm_SignalMerger_Inputs|
* |OVP_DocBegin_BoxAlgorithm_SignalMerger_Input1|
* The first input stream.
* |OVP_DocEnd_BoxAlgorithm_SignalMerger_Input1|
* |OVP_DocBegin_BoxAlgorithm_SignalMerger_Input2|
* The second input stream.
* |OVP_DocEnd_BoxAlgorithm_SignalMerger_Input2|
__________________________________________________________________
Outputs description
__________________________________________________________________
* |OVP_DocBegin_BoxAlgorithm_SignalMerger_Outputs|
* |OVP_DocEnd_BoxAlgorithm_SignalMerger_Outputs|
* |OVP_DocBegin_BoxAlgorithm_SignalMerger_Output1|
* The output stream contains all the channels grabbed from the different input streams.
* |OVP_DocEnd_BoxAlgorithm_SignalMerger_Output1|
__________________________________________________________________
Examples description
__________________________________________________________________
* |OVP_DocBegin_BoxAlgorithm_SignalMerger_Examples|
* |OVP_DocEnd_BoxAlgorithm_SignalMerger_Examples|
__________________________________________________________________
Miscellaneous description
__________________________________________________________________
* |OVP_DocBegin_BoxAlgorithm_SignalMerger_Miscellaneous|
* |OVP_DocEnd_BoxAlgorithm_SignalMerger_Miscellaneous|
*/
@@ -0,0 +1,64 @@
/**
* \page BoxAlgorithm_StreamedMatrixMultiplexer Streamed matrix multiplexer
__________________________________________________________________
Detailed description
__________________________________________________________________
* |OVP_DocBegin_BoxAlgorithm_StreamedMatrixMultiplexer_Description|
* This box multiplexes streamed matrix stream on a low level basis (at the EBML stream level actually).
* This means the box sorts the different buffers received from its inputs and sends all of them
* on its output. For correct results, this supposes the inputs have "homogeneous content" in the sense that
* they should have e.g. the same number of channels, in the same order, the same number of samples per buffer etc...
*
* This box is usually used after an epoching related split in the pipeline, when you want to process the signals
* in a similar manner for a similar purpose. This actually joins the pipelines in only one, dropping the need
* to edit and execute similar boxes.
*
* \b Warning: this box is usually misused and used in place of a \ref Doc_BoxAlgorithm_SignalMerger box.
* Please consider reading this documentation twice, and maybe read the \ref Doc_BoxAlgorithm_SignalMerger
* documentation once again as well :)
* |OVP_DocEnd_BoxAlgorithm_StreamedMatrixMultiplexer_Description|
__________________________________________________________________
Inputs description
__________________________________________________________________
* |OVP_DocBegin_BoxAlgorithm_StreamedMatrixMultiplexer_Inputs|
* You can add as many input as you want.
* |OVP_DocEnd_BoxAlgorithm_StreamedMatrixMultiplexer_Inputs|
* |OVP_DocBegin_BoxAlgorithm_StreamedMatrixMultiplexer_Input1|
* The first input stream.
* |OVP_DocEnd_BoxAlgorithm_StreamedMatrixMultiplexer_Input1|
* |OVP_DocBegin_BoxAlgorithm_StreamedMatrixMultiplexer_Input2|
* The second input stream.
* |OVP_DocEnd_BoxAlgorithm_StreamedMatrixMultiplexer_Input2|
__________________________________________________________________
Outputs description
__________________________________________________________________
* |OVP_DocBegin_BoxAlgorithm_StreamedMatrixMultiplexer_Outputs|
* |OVP_DocEnd_BoxAlgorithm_StreamedMatrixMultiplexer_Outputs|
* |OVP_DocBegin_BoxAlgorithm_StreamedMatrixMultiplexer_Output1|
* The output stream takes the header of the first stream and then sends buffers of the
* different input streams in a sorted way.
* |OVP_DocEnd_BoxAlgorithm_StreamedMatrixMultiplexer_Output1|
__________________________________________________________________
Examples description
__________________________________________________________________
* |OVP_DocBegin_BoxAlgorithm_StreamedMatrixMultiplexer_Examples|
* |OVP_DocEnd_BoxAlgorithm_StreamedMatrixMultiplexer_Examples|
__________________________________________________________________
Miscellaneous description
__________________________________________________________________
* |OVP_DocBegin_BoxAlgorithm_StreamedMatrixMultiplexer_Miscellaneous|
* |OVP_DocEnd_BoxAlgorithm_StreamedMatrixMultiplexer_Miscellaneous|
*/
@@ -0,0 +1,66 @@
.. _Doc_BoxAlgorithm_SignalMerger:
Signal Merger
=============
.. container:: attribution
:Author:
Yann Renard
:Company:
INRIA
.. image:: images/Doc_BoxAlgorithm_SignalMerger.png
This box merges several input streams in a single output stream. For instance,
if this box has two inputs with 8 channels each, the output will contain 16 channels.
It important to note that the input streams must have the same structure. That is
same sampling rate, same number of samples per buffer, and similar chunks dates.
The output channel order is as follows :
- n channels from input 1 (in the same order as in input 1)
- m channels from input 2
- ...
- p channels from input N
Such box has initially been proposed by Matthieu Goyat and Guillaume Lio but it
has been completely reimplemented in march 2011 because of unpredictable behaviors in
some conditions.
Inputs
------
.. csv-table::
:header: "Input Name", "Stream Type"
"Input 1", "Signal"
"Input 2", "Signal"
This box can receive as many inputs as necessary.
Input 1
~~~~~~~
The first input stream.
Input 2
~~~~~~~
The second input stream.
Outputs
-------
.. csv-table::
:header: "Output Name", "Stream Type"
"Merged", "Signal"
Merged
~~~~~~
The output stream contains all the channels grabbed from the different input streams.
@@ -0,0 +1,62 @@
.. _Doc_BoxAlgorithm_StreamedMatrixMultiplexer:
Streamed matrix multiplexer
===========================
.. container:: attribution
:Author:
Yann Renard
:Company:
INRIA/IRISA
.. image:: images/Doc_BoxAlgorithm_StreamedMatrixMultiplexer.png
This box multiplexes streamed matrix stream on a low level basis (at the EBML stream level actually).
This means the box sorts the different buffers received from its inputs and sends all of them
on its output. For correct results, this supposes the inputs have "homogeneous content" in the sense that
they should have e.g. the same number of channels, in the same order, the same number of samples per buffer etc...
This box is usually used after an epoching related split in the pipeline, when you want to process the signals
in a similar manner for a similar purpose. This actually joins the pipelines in only one, dropping the need
to edit and execute similar boxes.
**Warning:** this box is usually misused and used in place of a :ref:`Doc_BoxAlgorithm_SignalMerger` box.
Please consider reading this documentation twice, and maybe read the :ref:`Doc_BoxAlgorithm_SignalMerger`
documentation once again as well :)
Inputs
------
.. csv-table::
:header: "Input Name", "Stream Type"
"Input stream 1", "Streamed matrix"
"Input stream 2", "Streamed matrix"
You can add as many input as you want.
Input stream 1
~~~~~~~~~~~~~~
The first input stream.
Input stream 2
~~~~~~~~~~~~~~
The second input stream.
Outputs
-------
.. csv-table::
:header: "Output Name", "Stream Type"
"Multiplexed streamed matrix", "Streamed matrix"
Multiplexed streamed matrix
~~~~~~~~~~~~~~~~~~~~~~~~~~~
The output stream takes the header of the first stream and then sends buffers of the
different input streams in a sorted way.
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

@@ -0,0 +1,178 @@
#include "ovpCBoxAlgorithmSignalMerger.h"
namespace OpenViBE {
namespace Plugins {
namespace Streaming {
bool CBoxAlgorithmSignalMerger::initialize()
{
const size_t nInput = this->getStaticBoxContext().getInputCount();
for (size_t i = 0; i < nInput; ++i) { m_decoders.push_back(new Toolkit::TSignalDecoder<CBoxAlgorithmSignalMerger>(*this, i)); }
m_encoder = new Toolkit::TSignalEncoder<CBoxAlgorithmSignalMerger>(*this, 0);
return true;
}
bool CBoxAlgorithmSignalMerger::uninitialize()
{
const size_t nInput = this->getStaticBoxContext().getInputCount();
m_encoder->uninitialize();
delete m_encoder;
for (size_t i = 0; i < nInput; ++i)
{
m_decoders[i]->uninitialize();
delete m_decoders[i];
}
m_decoders.clear();
return true;
}
bool CBoxAlgorithmSignalMerger::processInput(const size_t index)
{
IDynamicBoxContext& boxContext = this->getDynamicBoxContext();
const size_t nInput = this->getStaticBoxContext().getInputCount();
if (boxContext.getInputChunkCount(0) == 0) { return true; }
const uint64_t tStart = boxContext.getInputChunkStartTime(0, 0);
const uint64_t tEnd = boxContext.getInputChunkEndTime(0, 0);
for (size_t i = 1; i < nInput; ++i)
{
if (boxContext.getInputChunkCount(i) == 0) { return true; }
OV_ERROR_UNLESS_KRF(tStart == boxContext.getInputChunkStartTime(i, 0),
"Invalid start time [" << boxContext.getInputChunkStartTime(i, 0) << "] on input [" << i
<< "] (expected value must match start time on input 0 [" << tStart << "])",
Kernel::ErrorType::BadInput);
OV_ERROR_UNLESS_KRF(tEnd == boxContext.getInputChunkEndTime(i, 0),
"Invalid end time [" << boxContext.getInputChunkEndTime(i, 0) << "] on input [" << i
<< "] (expected value must match end time on input 0 [" << tEnd << "])",
Kernel::ErrorType::BadInput);
}
if (index == nInput - 1)
{
for (size_t i = 1; i < nInput; ++i)
{
OV_ERROR_UNLESS_KRF(boxContext.getInputChunkCount(0) >= boxContext.getInputChunkCount(i),
"Invalid input chunk count [" << boxContext.getInputChunkCount(i) << "] on input [" << i
<< "] (expected value must be <= to chunk count on input 0 [" << boxContext.getInputChunkCount(0) << "])",
Kernel::ErrorType::BadInput);
}
}
this->getBoxAlgorithmContext()->markAlgorithmAsReadyToProcess();
return true;
}
bool CBoxAlgorithmSignalMerger::process()
{
Kernel::IBoxIO& boxContext = this->getDynamicBoxContext();
const size_t nInput = this->getStaticBoxContext().getInputCount();
size_t nChunk = boxContext.getInputChunkCount(0);
for (size_t input = 1; input < nInput; ++input) { if (boxContext.getInputChunkCount(input) < nChunk) { nChunk = boxContext.getInputChunkCount(input); } }
for (size_t c = 0; c < nChunk; ++c)
{
size_t nSamplePerBlock = 0;
size_t nChannel = 0;
size_t nHeader = 0;
size_t nBuffer = 0;
size_t nEnd = 0;
for (size_t i = 0; i < nInput; ++i)
{
m_decoders[i]->decode(c);
const CMatrix* op_matrix = m_decoders[i]->getOutputMatrix();
if (m_decoders[i]->isHeaderReceived())
{
nHeader++;
if (i == 0)
{
nSamplePerBlock = op_matrix->getDimensionSize(1);
nChannel = op_matrix->getDimensionSize(0);
}
else
{
// Check that properties agree
OV_ERROR_UNLESS_KRF(nSamplePerBlock == op_matrix->getDimensionSize(1),
"Output matrix dimension [" << op_matrix->getDimensionSize(1) << "] on input [" << i
<< "] must match sample count per block [" << nSamplePerBlock << "]",
Kernel::ErrorType::BadInput);
OV_ERROR_UNLESS_KRF(m_decoders[0]->getOutputSamplingRate() == m_decoders[i]->getOutputSamplingRate(),
"Output sampling rate [" << m_decoders[i]->getOutputSamplingRate() << "] on input [" << i
<< "] must match the sampling rate on input 0 [" << m_decoders[0]->getOutputSamplingRate() << "]",
Kernel::ErrorType::BadInput);
nChannel += op_matrix->getDimensionSize(0);
}
}
if (m_decoders[i]->isBufferReceived()) { nBuffer++; }
if (m_decoders[i]->isEndReceived()) { nEnd++; }
}
OV_ERROR_UNLESS_KRF(!nHeader || nHeader == nInput, "Received [" << nHeader << "] headers for [" << nInput << "] declared inputs", Kernel::ErrorType::BadInput);
OV_ERROR_UNLESS_KRF(!nBuffer || nBuffer == nInput, "Received [" << nBuffer << "] buffers for [" << nInput << "] declared inputs", Kernel::ErrorType::BadInput);
OV_ERROR_UNLESS_KRF(!nEnd || nEnd == nInput, "Received [" << nEnd << "] ends for [" << nInput << "] declared inputs", Kernel::ErrorType::BadInput);
if (nHeader)
{
// We have received headers from all inputs
CMatrix* ip_matrix = m_encoder->getInputMatrix();
ip_matrix->resize(nChannel, nSamplePerBlock);
for (size_t i = 0, k = 0; i < nInput; ++i)
{
const CMatrix* op_matrix = m_decoders[i]->getOutputMatrix();
for (size_t j = 0; j < op_matrix->getDimensionSize(0); j++, k++) { ip_matrix->setDimensionLabel(0, k, op_matrix->getDimensionLabel(0, j)); }
}
const uint64_t sampling = m_decoders[0]->getOutputSamplingRate();
m_encoder->getInputSamplingRate() = sampling;
this->getLogManager() << Kernel::LogLevel_Debug << "Setting sampling rate to " << sampling << "\n";
m_encoder->encodeHeader();
boxContext.markOutputAsReadyToSend(0, boxContext.getInputChunkStartTime(0, c), boxContext.getInputChunkEndTime(0, c));
}
if (nBuffer)
{
// We have received one buffer from each input
CMatrix* ip_matrix = m_encoder->getInputMatrix();
nSamplePerBlock = ip_matrix->getDimensionSize(1);
for (size_t i = 0, k = 0; i < nInput; ++i)
{
CMatrix* op_matrix = m_decoders[i]->getOutputMatrix();
for (size_t j = 0; j < op_matrix->getDimensionSize(0); j++, k++)
{
memcpy(ip_matrix->getBuffer() + k * nSamplePerBlock, op_matrix->getBuffer() + j * nSamplePerBlock, nSamplePerBlock * sizeof(double));
}
}
m_encoder->encodeBuffer();
boxContext.markOutputAsReadyToSend(0, boxContext.getInputChunkStartTime(0, c), boxContext.getInputChunkEndTime(0, c));
}
if (nEnd)
{
// We have received one end from each input
m_encoder->encodeEnd();
boxContext.markOutputAsReadyToSend(0, boxContext.getInputChunkStartTime(0, c), boxContext.getInputChunkEndTime(0, c));
}
}
return true;
}
} // namespace Streaming
} // namespace Plugins
} // namespace OpenViBE
@@ -0,0 +1,74 @@
#pragma once
#include "../ovp_defines.h"
#include <openvibe/ov_all.h>
#include <toolkit/ovtk_all.h>
#include <vector>
namespace OpenViBE {
namespace Plugins {
namespace Streaming {
class CBoxAlgorithmSignalMerger final : public Toolkit::TBoxAlgorithm<IBoxAlgorithm>
{
public:
void release() override { delete this; }
bool initialize() override;
bool uninitialize() override;
bool processInput(const size_t index) override;
bool process() override;
_IsDerivedFromClass_Final_(Toolkit::TBoxAlgorithm<IBoxAlgorithm>, OVP_ClassId_BoxAlgorithm_SignalMerger)
protected:
std::vector<Toolkit::TSignalDecoder<CBoxAlgorithmSignalMerger>*> m_decoders;
Toolkit::TSignalEncoder<CBoxAlgorithmSignalMerger>* m_encoder = nullptr;
};
class CBoxAlgorithmSignalMergerListener final : public Toolkit::TBoxListener<IBoxListener>
{
public:
bool onInputAdded(Kernel::IBox& box, const size_t index) override
{
box.setInputName(index, ("Input " + std::to_string(index + 1)).c_str());
box.setInputType(index, OV_TypeId_Signal);
return true;
}
_IsDerivedFromClass_Final_(Toolkit::TBoxListener<IBoxListener>, CIdentifier::undefined())
};
class CBoxAlgorithmSignalMergerDesc final : public IBoxAlgorithmDesc
{
public:
void release() override { }
CString getName() const override { return CString("Signal Merger"); }
CString getAuthorName() const override { return CString("Yann Renard"); }
CString getAuthorCompanyName() const override { return CString("INRIA"); }
CString getShortDescription() const override { return CString("Merges several input streams into a single output stream"); }
CString getDetailedDescription() const override { return CString(""); }
CString getCategory() const override { return CString("Streaming"); }
CString getVersion() const override { return CString("1.0"); }
CString getSoftwareComponent() const override { return CString("openvibe-sdk"); }
CString getAddedSoftwareVersion() const override { return CString("0.0.0"); }
CString getUpdatedSoftwareVersion() const override { return CString("0.0.0"); }
CIdentifier getCreatedClass() const override { return OVP_ClassId_BoxAlgorithm_SignalMerger; }
IPluginObject* create() override { return new CBoxAlgorithmSignalMerger; }
IBoxListener* createBoxListener() const override { return new CBoxAlgorithmSignalMergerListener; }
void releaseBoxListener(IBoxListener* listener) const override { delete listener; }
bool getBoxPrototype(Kernel::IBoxProto& prototype) const override
{
prototype.addInput("Input 1", OV_TypeId_Signal);
prototype.addInput("Input 2", OV_TypeId_Signal);
prototype.addOutput("Merged", OV_TypeId_Signal);
prototype.addFlag(Kernel::BoxFlag_CanAddInput);
return true;
}
_IsDerivedFromClass_Final_(IBoxAlgorithmDesc, OVP_ClassId_BoxAlgorithm_SignalMergerDesc)
};
} // namespace Streaming
} // namespace Plugins
} // namespace OpenViBE
@@ -0,0 +1,64 @@
#include "ovpCBoxAlgorithmStreamedMatrixMultiplexer.h"
namespace OpenViBE {
namespace Plugins {
namespace Streaming {
bool CBoxAlgorithmStreamedMatrixMultiplexer::initialize()
{
m_lastStartTime = 0;
m_lastEndTime = 0;
m_headerSent = false;
return true;
}
bool CBoxAlgorithmStreamedMatrixMultiplexer::uninitialize() { return true; }
bool CBoxAlgorithmStreamedMatrixMultiplexer::processInput(const size_t /*index*/)
{
getBoxAlgorithmContext()->markAlgorithmAsReadyToProcess();
return true;
}
bool CBoxAlgorithmStreamedMatrixMultiplexer::process()
{
Kernel::IBoxIO& boxContext = this->getDynamicBoxContext();
const size_t nInput = this->getStaticBoxContext().getInputCount();
for (size_t i = 0; i < nInput; ++i)
{
for (size_t j = 0; j < boxContext.getInputChunkCount(i); ++j)
{
const IMemoryBuffer* iBuffer = boxContext.getInputChunk(i, j);
const uint64_t tStart = boxContext.getInputChunkStartTime(i, j);
const uint64_t tEnd = boxContext.getInputChunkEndTime(i, j);
if ((!m_headerSent && tStart == tEnd) || (m_headerSent && tStart != tEnd))
{
IMemoryBuffer* oBuffer = boxContext.getOutputChunk(0);
oBuffer->setSize(iBuffer->getSize(), true);
memcpy(oBuffer->getDirectPointer(), iBuffer->getDirectPointer(), iBuffer->getSize());
OV_ERROR_UNLESS_KRF(tStart >= m_lastStartTime && tEnd >= m_lastEndTime,
"Invalid chunk times with start = [" << tStart << "] and end = [" << tEnd << "] while last chunk has start = [" <<
m_lastStartTime << "] and end = [" << m_lastEndTime << "]",
Kernel::ErrorType::BadInput);
m_lastStartTime = tStart;
m_lastEndTime = tEnd;
boxContext.markOutputAsReadyToSend(0, tStart, tEnd);
m_headerSent = true;
}
boxContext.markInputAsDeprecated(i, j);
}
}
return true;
}
} // namespace Streaming
} // namespace Plugins
} // namespace OpenViBE
@@ -0,0 +1,138 @@
#pragma once
#include "../ovp_defines.h"
#include <openvibe/ov_all.h>
#include <toolkit/ovtk_all.h>
namespace OpenViBE {
namespace Plugins {
namespace Streaming {
class CBoxAlgorithmStreamedMatrixMultiplexer final : virtual public Toolkit::TBoxAlgorithm<IBoxAlgorithm>
{
public:
void release() override { delete this; }
bool initialize() override;
bool uninitialize() override;
bool processInput(const size_t index) override;
bool process() override;
_IsDerivedFromClass_Final_(Toolkit::TBoxAlgorithm<IBoxAlgorithm>, OVP_ClassId_BoxAlgorithm_StreamedMatrixMultiplexer)
protected:
uint64_t m_lastStartTime = 0;
uint64_t m_lastEndTime = 0;
bool m_headerSent = false;
};
class CBoxAlgorithmStreamedMatrixMultiplexerListener final : public Toolkit::TBoxListener<IBoxListener>
{
public:
bool check(Kernel::IBox& box) const
{
for (size_t i = 0; i < box.getInputCount(); ++i) { box.setInputName(i, ("Input stream " + std::to_string(i + 1)).c_str()); }
return true;
}
bool onInputAdded(Kernel::IBox& box, const size_t index) override
{
CIdentifier typeID = CIdentifier::undefined();
box.getOutputType(0, typeID);
box.setInputType(index, typeID);
return this->check(box);
}
bool onInputRemoved(Kernel::IBox& box, const size_t /*index*/) override
{
CIdentifier typeID = CIdentifier::undefined();
box.getOutputType(0, typeID);
while (box.getInputCount() < 2) { box.addInput("", typeID); }
return this->check(box);
}
bool onInputTypeChanged(Kernel::IBox& box, const size_t index) override
{
CIdentifier typeID = CIdentifier::undefined();
box.getInputType(index, typeID);
if (this->getTypeManager().isDerivedFromStream(typeID, OV_TypeId_StreamedMatrix))
{
for (size_t i = 0; i < box.getInputCount(); ++i) { box.setInputType(i, typeID); }
box.setOutputType(0, typeID);
}
else
{
box.getOutputType(0, typeID);
box.setInputType(index, typeID);
}
return true;
}
bool onOutputTypeChanged(Kernel::IBox& box, const size_t /*index*/) override
{
CIdentifier typeID = CIdentifier::undefined();
box.getOutputType(0, typeID);
if (this->getTypeManager().isDerivedFromStream(typeID, OV_TypeId_StreamedMatrix))
{
for (size_t i = 0; i < box.getInputCount(); ++i) { box.setInputType(i, typeID); }
}
else
{
box.getInputType(0, typeID);
box.setOutputType(0, typeID);
}
return true;
}
_IsDerivedFromClass_Final_(Toolkit::TBoxListener<IBoxListener>, CIdentifier::undefined())
};
class CBoxAlgorithmStreamedMatrixMultiplexerDesc final : virtual public IBoxAlgorithmDesc
{
public:
void release() override { }
CString getName() const override { return CString("Streamed matrix multiplexer"); }
CString getAuthorName() const override { return CString("Yann Renard"); }
CString getAuthorCompanyName() const override { return CString("INRIA/IRISA"); }
CString getShortDescription() const override { return CString("Multiplexes streamed matrix buffers in a new stream"); }
CString getDetailedDescription() const override { return CString(""); }
CString getCategory() const override { return CString("Streaming"); }
CString getVersion() const override { return CString("1.0"); }
CString getSoftwareComponent() const override { return CString("openvibe-sdk"); }
CString getAddedSoftwareVersion() const override { return CString("0.0.0"); }
CString getUpdatedSoftwareVersion() const override { return CString("0.0.0"); }
CIdentifier getCreatedClass() const override { return OVP_ClassId_BoxAlgorithm_StreamedMatrixMultiplexer; }
IPluginObject* create() override { return new CBoxAlgorithmStreamedMatrixMultiplexer; }
IBoxListener* createBoxListener() const override { return new CBoxAlgorithmStreamedMatrixMultiplexerListener; }
void releaseBoxListener(IBoxListener* listener) const override { delete listener; }
bool getBoxPrototype(Kernel::IBoxProto& prototype) const override
{
prototype.addInput("Input stream 1", OV_TypeId_StreamedMatrix);
prototype.addInput("Input stream 2", OV_TypeId_StreamedMatrix);
prototype.addOutput("Multiplexed streamed matrix", OV_TypeId_StreamedMatrix);
prototype.addFlag(Kernel::BoxFlag_CanAddInput);
prototype.addFlag(Kernel::BoxFlag_CanModifyInput);
prototype.addFlag(Kernel::BoxFlag_CanModifyOutput);
prototype.addInputSupport(OV_TypeId_StreamedMatrix);
prototype.addInputSupport(OV_TypeId_ChannelLocalisation);
prototype.addInputSupport(OV_TypeId_FeatureVector);
prototype.addInputSupport(OV_TypeId_Signal);
prototype.addInputSupport(OV_TypeId_Spectrum);
return true;
}
_IsDerivedFromClass_Final_(IBoxAlgorithmDesc, OVP_ClassId_BoxAlgorithm_StreamedMatrixMultiplexerDesc)
};
} // namespace Streaming
} // namespace Plugins
} // namespace OpenViBE
@@ -0,0 +1,14 @@
#pragma once
// Boxes
//---------------------------------------------------------------------------------------------------
#define OVP_ClassId_BoxAlgorithm_SignalMerger OpenViBE::CIdentifier(0x4BF9326F, 0x75603102)
#define OVP_ClassId_BoxAlgorithm_SignalMergerDesc OpenViBE::CIdentifier(0x7A684C44, 0x23BA70A5)
#define OVP_ClassId_BoxAlgorithm_StreamedMatrixMultiplexer OpenViBE::CIdentifier(0x7A12298B, 0x785F4D42)
#define OVP_ClassId_BoxAlgorithm_StreamedMatrixMultiplexerDesc OpenViBE::CIdentifier(0x0B420425, 0x3F602DE7)
// Global defines
//---------------------------------------------------------------------------------------------------
#ifdef TARGET_HAS_ThirdPartyOpenViBEPluginsGlobalDefines
#include "ovp_global_defines.h"
#endif // TARGET_HAS_ThirdPartyOpenViBEPluginsGlobalDefines
@@ -0,0 +1,19 @@
#include "ovp_defines.h"
#include "box-algorithms/ovpCBoxAlgorithmStreamedMatrixMultiplexer.h"
#include "box-algorithms/ovpCBoxAlgorithmSignalMerger.h"
#include <vector>
namespace OpenViBE {
namespace Plugins {
namespace Streaming {
OVP_Declare_Begin()
OVP_Declare_New(CBoxAlgorithmStreamedMatrixMultiplexerDesc);
OVP_Declare_New(CBoxAlgorithmSignalMergerDesc);
OVP_Declare_End()
} // namespace Streaming
} // namespace Plugins
} // namespace OpenViBE