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,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