avoid allocating memory in the server real-time processing routine
This commit is contained in:
parent
7ee9fc2a67
commit
2c443c7aef
7 changed files with 133 additions and 125 deletions
|
@ -64,28 +64,26 @@ bool CNetBuf::Put ( const CVector<uint8_t>& vecbyData,
|
||||||
return bPutOK;
|
return bPutOK;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CNetBuf::Get ( CVector<uint8_t>& vecbyData )
|
bool CNetBuf::Get ( CVector<uint8_t>& vecbyData,
|
||||||
|
const int iOutSize )
|
||||||
{
|
{
|
||||||
bool bGetOK = true; // init return value
|
bool bGetOK = true; // init return value
|
||||||
|
|
||||||
// get size of data to be get from the buffer
|
|
||||||
const int iInSize = vecbyData.Size();
|
|
||||||
|
|
||||||
// check size
|
// check size
|
||||||
if ( ( iInSize == 0 ) || ( iInSize != iBlockSize ) )
|
if ( ( iOutSize == 0 ) || ( iOutSize != iBlockSize ) )
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if there is not enough data available
|
// check if there is not enough data available
|
||||||
if ( GetAvailData() < iInSize )
|
if ( GetAvailData() < iOutSize )
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// copy data from internal buffer in output buffer (implemented in base
|
// copy data from internal buffer in output buffer (implemented in base
|
||||||
// class)
|
// class)
|
||||||
CBufferBase<uint8_t>::Get ( vecbyData );
|
CBufferBase<uint8_t>::Get ( vecbyData, iOutSize );
|
||||||
|
|
||||||
return bGetOK;
|
return bGetOK;
|
||||||
}
|
}
|
||||||
|
@ -180,16 +178,17 @@ bool CNetBufWithStats::Put ( const CVector<uint8_t>& vecbyData,
|
||||||
return bPutOK;
|
return bPutOK;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CNetBufWithStats::Get ( CVector<uint8_t>& vecbyData )
|
bool CNetBufWithStats::Get ( CVector<uint8_t>& vecbyData,
|
||||||
|
const int iOutSize )
|
||||||
{
|
{
|
||||||
// call base class Get
|
// call base class Get
|
||||||
const bool bGetOK = CNetBuf::Get ( vecbyData );
|
const bool bGetOK = CNetBuf::Get ( vecbyData, iOutSize );
|
||||||
|
|
||||||
// update statistics calculations
|
// update statistics calculations
|
||||||
for ( int i = 0; i < NUM_STAT_SIMULATION_BUFFERS; i++ )
|
for ( int i = 0; i < NUM_STAT_SIMULATION_BUFFERS; i++ )
|
||||||
{
|
{
|
||||||
ErrorRateStatistic[i].Update (
|
ErrorRateStatistic[i].Update (
|
||||||
!SimulationBuffer[i].Get ( vecbyData ) );
|
!SimulationBuffer[i].Get ( vecbyData, iOutSize ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
// update auto setting
|
// update auto setting
|
||||||
|
|
31
src/buffer.h
31
src/buffer.h
|
@ -72,6 +72,7 @@ public:
|
||||||
|
|
||||||
// get maximum number of data to be copied
|
// get maximum number of data to be copied
|
||||||
int iCopyLen = GetAvailData();
|
int iCopyLen = GetAvailData();
|
||||||
|
|
||||||
if ( iCopyLen > iNewMemSize )
|
if ( iCopyLen > iNewMemSize )
|
||||||
{
|
{
|
||||||
iCopyLen = iNewMemSize;
|
iCopyLen = iNewMemSize;
|
||||||
|
@ -176,6 +177,7 @@ public:
|
||||||
// in this simulation only the buffer pointers and the buffer state
|
// in this simulation only the buffer pointers and the buffer state
|
||||||
// is updated, no actual data is transferred
|
// is updated, no actual data is transferred
|
||||||
iPutPos += iInSize;
|
iPutPos += iInSize;
|
||||||
|
|
||||||
if ( iPutPos >= iMemSize )
|
if ( iPutPos >= iMemSize )
|
||||||
{
|
{
|
||||||
iPutPos -= iMemSize;
|
iPutPos -= iMemSize;
|
||||||
|
@ -185,6 +187,7 @@ public:
|
||||||
{
|
{
|
||||||
// copy new data in internal buffer
|
// copy new data in internal buffer
|
||||||
int iCurPos = 0;
|
int iCurPos = 0;
|
||||||
|
|
||||||
if ( iPutPos + iInSize > iMemSize )
|
if ( iPutPos + iInSize > iMemSize )
|
||||||
{
|
{
|
||||||
// remaining space size for second block
|
// remaining space size for second block
|
||||||
|
@ -233,16 +236,15 @@ public:
|
||||||
return true; // no error check in base class, alyways return ok
|
return true; // no error check in base class, alyways return ok
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool Get ( CVector<TData>& vecData )
|
virtual bool Get ( CVector<TData>& vecData,
|
||||||
|
const int iOutSize )
|
||||||
{
|
{
|
||||||
// get size of data to be get from the buffer
|
|
||||||
const int iInSize = vecData.Size();
|
|
||||||
|
|
||||||
if ( bIsSimulation )
|
if ( bIsSimulation )
|
||||||
{
|
{
|
||||||
// in this simulation only the buffer pointers and the buffer state
|
// in this simulation only the buffer pointers and the buffer state
|
||||||
// is updated, no actual data is transferred
|
// is updated, no actual data is transferred
|
||||||
iGetPos += iInSize;
|
iGetPos += iOutSize;
|
||||||
|
|
||||||
if ( iGetPos >= iMemSize )
|
if ( iGetPos >= iMemSize )
|
||||||
{
|
{
|
||||||
iGetPos -= iMemSize;
|
iGetPos -= iMemSize;
|
||||||
|
@ -252,10 +254,11 @@ public:
|
||||||
{
|
{
|
||||||
// copy data from internal buffer in output buffer
|
// copy data from internal buffer in output buffer
|
||||||
int iCurPos = 0;
|
int iCurPos = 0;
|
||||||
if ( iGetPos + iInSize > iMemSize )
|
|
||||||
|
if ( iGetPos + iOutSize > iMemSize )
|
||||||
{
|
{
|
||||||
// remaining data size for second block
|
// remaining data size for second block
|
||||||
const int iRemData = iGetPos + iInSize - iMemSize;
|
const int iRemData = iGetPos + iOutSize - iMemSize;
|
||||||
|
|
||||||
// data must be read in two steps because of wrap around
|
// data must be read in two steps because of wrap around
|
||||||
while ( iGetPos < iMemSize )
|
while ( iGetPos < iMemSize )
|
||||||
|
@ -272,12 +275,12 @@ public:
|
||||||
{
|
{
|
||||||
// data can be read in one step
|
// data can be read in one step
|
||||||
std::copy ( vecMemory.begin() + iGetPos,
|
std::copy ( vecMemory.begin() + iGetPos,
|
||||||
vecMemory.begin() + iGetPos + iInSize,
|
vecMemory.begin() + iGetPos + iOutSize,
|
||||||
vecData.begin() );
|
vecData.begin() );
|
||||||
|
|
||||||
// set the get position one block further (no wrap around needs
|
// set the get position one block further (no wrap around needs
|
||||||
// to be considered here)
|
// to be considered here)
|
||||||
iGetPos += iInSize;
|
iGetPos += iOutSize;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -383,7 +386,7 @@ public:
|
||||||
int GetSize() { return iMemSize / iBlockSize; }
|
int GetSize() { return iMemSize / iBlockSize; }
|
||||||
|
|
||||||
virtual bool Put ( const CVector<uint8_t>& vecbyData, const int iInSize );
|
virtual bool Put ( const CVector<uint8_t>& vecbyData, const int iInSize );
|
||||||
virtual bool Get ( CVector<uint8_t>& vecbyData );
|
virtual bool Get ( CVector<uint8_t>& vecbyData, const int iOutSize );
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
int iBlockSize;
|
int iBlockSize;
|
||||||
|
@ -401,7 +404,7 @@ public:
|
||||||
const bool bPreserve = false );
|
const bool bPreserve = false );
|
||||||
|
|
||||||
virtual bool Put ( const CVector<uint8_t>& vecbyData, const int iInSize );
|
virtual bool Put ( const CVector<uint8_t>& vecbyData, const int iInSize );
|
||||||
virtual bool Get ( CVector<uint8_t>& vecbyData );
|
virtual bool Get ( CVector<uint8_t>& vecbyData, const int iOutSize );
|
||||||
|
|
||||||
int GetAutoSetting() { return iCurAutoBufferSizeSetting; }
|
int GetAutoSetting() { return iCurAutoBufferSizeSetting; }
|
||||||
void GetErrorRates ( CVector<double>& vecErrRates, double& dLimit );
|
void GetErrorRates ( CVector<double>& vecErrRates, double& dLimit );
|
||||||
|
@ -444,11 +447,11 @@ public:
|
||||||
|
|
||||||
int GetSize() const { return iMemSize; }
|
int GetSize() const { return iMemSize; }
|
||||||
|
|
||||||
bool Put ( const CVector<TData>& vecsData )
|
bool Put ( const CVector<TData>& vecsData,
|
||||||
|
const int iVecSize )
|
||||||
{
|
{
|
||||||
// calculate the input size and the end position after copying
|
// calculate the input size and the end position after copying
|
||||||
const int iVecSize = vecsData.Size();
|
const int iEnd = iPutPos + iVecSize;
|
||||||
const int iEnd = iPutPos + iVecSize;
|
|
||||||
|
|
||||||
// first check for buffer overrun
|
// first check for buffer overrun
|
||||||
if ( iEnd <= iMemSize )
|
if ( iEnd <= iMemSize )
|
||||||
|
|
|
@ -51,6 +51,9 @@ CChannel::CChannel ( const bool bNIsServer ) :
|
||||||
|
|
||||||
|
|
||||||
// Connections -------------------------------------------------------------
|
// Connections -------------------------------------------------------------
|
||||||
|
qRegisterMetaType<CVector<uint8_t> > ( "CVector<uint8_t>" );
|
||||||
|
qRegisterMetaType<CHostAddress> ( "CHostAddress" );
|
||||||
|
|
||||||
QObject::connect ( &Protocol,
|
QObject::connect ( &Protocol,
|
||||||
SIGNAL ( MessReadyForSending ( CVector<uint8_t> ) ),
|
SIGNAL ( MessReadyForSending ( CVector<uint8_t> ) ),
|
||||||
this, SLOT ( OnSendProtMessage ( CVector<uint8_t> ) ) );
|
this, SLOT ( OnSendProtMessage ( CVector<uint8_t> ) ) );
|
||||||
|
@ -433,7 +436,7 @@ void CChannel::Disconnect()
|
||||||
}
|
}
|
||||||
|
|
||||||
EPutDataStat CChannel::PutData ( const CVector<uint8_t>& vecbyData,
|
EPutDataStat CChannel::PutData ( const CVector<uint8_t>& vecbyData,
|
||||||
int iNumBytes )
|
const int iNumBytes )
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
Note that this function might be called from a different thread (separate
|
Note that this function might be called from a different thread (separate
|
||||||
|
@ -558,14 +561,15 @@ EPutDataStat CChannel::PutData ( const CVector<uint8_t>& vecbyData,
|
||||||
return eRet;
|
return eRet;
|
||||||
}
|
}
|
||||||
|
|
||||||
EGetDataStat CChannel::GetData ( CVector<uint8_t>& vecbyData )
|
EGetDataStat CChannel::GetData ( CVector<uint8_t>& vecbyData,
|
||||||
|
const int iNumBytes )
|
||||||
{
|
{
|
||||||
EGetDataStat eGetStatus;
|
EGetDataStat eGetStatus;
|
||||||
|
|
||||||
Mutex.lock();
|
Mutex.lock();
|
||||||
{
|
{
|
||||||
// the socket access must be inside a mutex
|
// the socket access must be inside a mutex
|
||||||
const bool bSockBufState = SockBuf.Get ( vecbyData );
|
const bool bSockBufState = SockBuf.Get ( vecbyData, iNumBytes );
|
||||||
|
|
||||||
// decrease time-out counter
|
// decrease time-out counter
|
||||||
if ( iConTimeOut > 0 )
|
if ( iConTimeOut > 0 )
|
||||||
|
@ -622,13 +626,14 @@ EGetDataStat CChannel::GetData ( CVector<uint8_t>& vecbyData )
|
||||||
}
|
}
|
||||||
|
|
||||||
void CChannel::PrepAndSendPacket ( CSocket* pSocket,
|
void CChannel::PrepAndSendPacket ( CSocket* pSocket,
|
||||||
const CVector<uint8_t>& vecbyNPacket )
|
const CVector<uint8_t>& vecbyNPacket,
|
||||||
|
const int iNPacketLen )
|
||||||
{
|
{
|
||||||
QMutexLocker locker ( &Mutex );
|
QMutexLocker locker ( &Mutex );
|
||||||
|
|
||||||
// use conversion buffer to convert sound card block size in network
|
// use conversion buffer to convert sound card block size in network
|
||||||
// block size
|
// block size
|
||||||
if ( ConvBuf.Put ( vecbyNPacket ) )
|
if ( ConvBuf.Put ( vecbyNPacket, iNPacketLen ) )
|
||||||
{
|
{
|
||||||
pSocket->SendPacket ( ConvBuf.Get(), GetAddress() );
|
pSocket->SendPacket ( ConvBuf.Get(), GetAddress() );
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,11 +64,13 @@ public:
|
||||||
CChannel ( const bool bNIsServer = true );
|
CChannel ( const bool bNIsServer = true );
|
||||||
|
|
||||||
EPutDataStat PutData ( const CVector<uint8_t>& vecbyData,
|
EPutDataStat PutData ( const CVector<uint8_t>& vecbyData,
|
||||||
int iNumBytes );
|
const int iNumBytes );
|
||||||
EGetDataStat GetData ( CVector<uint8_t>& vecbyData );
|
EGetDataStat GetData ( CVector<uint8_t>& vecbyData,
|
||||||
|
const int iNumBytes );
|
||||||
|
|
||||||
void PrepAndSendPacket ( CSocket* pSocket,
|
void PrepAndSendPacket ( CSocket* pSocket,
|
||||||
const CVector<uint8_t>& vecbyNPacket );
|
const CVector<uint8_t>& vecbyNPacket,
|
||||||
|
const int iNPacketLen );
|
||||||
|
|
||||||
void ResetTimeOutCounter() { iConTimeOut = iConTimeOutStartVal; }
|
void ResetTimeOutCounter() { iConTimeOut = iConTimeOutStartVal; }
|
||||||
bool IsConnected() const { return iConTimeOut > 0; }
|
bool IsConnected() const { return iConTimeOut > 0; }
|
||||||
|
|
|
@ -896,16 +896,16 @@ void CClient::ProcessSndCrdAudioData ( CVector<int16_t>& vecsStereoSndCrd )
|
||||||
while ( SndCrdConversionBufferIn.GetAvailData() >= iStereoBlockSizeSam )
|
while ( SndCrdConversionBufferIn.GetAvailData() >= iStereoBlockSizeSam )
|
||||||
{
|
{
|
||||||
// get one block of data for processing
|
// get one block of data for processing
|
||||||
SndCrdConversionBufferIn.Get ( vecDataConvBuf );
|
SndCrdConversionBufferIn.Get ( vecDataConvBuf, iStereoBlockSizeSam );
|
||||||
|
|
||||||
// process audio data
|
// process audio data
|
||||||
ProcessAudioDataIntern ( vecDataConvBuf );
|
ProcessAudioDataIntern ( vecDataConvBuf );
|
||||||
|
|
||||||
SndCrdConversionBufferOut.Put ( vecDataConvBuf, vecDataConvBuf.Size() );
|
SndCrdConversionBufferOut.Put ( vecDataConvBuf, iStereoBlockSizeSam );
|
||||||
}
|
}
|
||||||
|
|
||||||
// get processed sound card block out of the conversion buffer
|
// get processed sound card block out of the conversion buffer
|
||||||
SndCrdConversionBufferOut.Get ( vecsStereoSndCrd );
|
SndCrdConversionBufferOut.Get ( vecsStereoSndCrd, vecsStereoSndCrd.Size() );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1092,7 +1092,9 @@ void CClient::ProcessAudioDataIntern ( CVector<int16_t>& vecsStereoSndCrd )
|
||||||
}
|
}
|
||||||
|
|
||||||
// send coded audio through the network
|
// send coded audio through the network
|
||||||
Channel.PrepAndSendPacket ( &Socket, vecCeltData );
|
Channel.PrepAndSendPacket ( &Socket,
|
||||||
|
vecCeltData,
|
||||||
|
iCeltNumCodedBytes );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1119,7 +1121,7 @@ void CClient::ProcessAudioDataIntern ( CVector<int16_t>& vecsStereoSndCrd )
|
||||||
{
|
{
|
||||||
// receive a new block
|
// receive a new block
|
||||||
const bool bReceiveDataOk =
|
const bool bReceiveDataOk =
|
||||||
( Channel.GetData ( vecbyNetwData ) == GS_BUFFER_OK );
|
( Channel.GetData ( vecbyNetwData, iCeltNumCodedBytes ) == GS_BUFFER_OK );
|
||||||
|
|
||||||
// invalidate the buffer OK status flag if necessary
|
// invalidate the buffer OK status flag if necessary
|
||||||
if ( !bReceiveDataOk )
|
if ( !bReceiveDataOk )
|
||||||
|
|
108
src/server.cpp
108
src/server.cpp
|
@ -311,10 +311,33 @@ CServer::CServer ( const int iNewMaxNumChan,
|
||||||
vstrChatColors[4] = "maroon";
|
vstrChatColors[4] = "maroon";
|
||||||
vstrChatColors[5] = "coral";
|
vstrChatColors[5] = "coral";
|
||||||
|
|
||||||
// allocate memory for the channel IDs vector for the current connected
|
|
||||||
// channels where we assume the worst case that all possible channels are
|
// To avoid audio clitches, in the entire realtime timer audio processing
|
||||||
// used
|
// routine including the ProcessData no memory must be allocated. Since we
|
||||||
|
// do not know the required sizes for the vectors, we allocate memory for
|
||||||
|
// the worst case here:
|
||||||
|
|
||||||
|
// we always use stereo audio buffers (which is the worst case)
|
||||||
|
vecsSendData.Init ( 2 * SYSTEM_FRAME_SIZE_SAMPLES );
|
||||||
|
|
||||||
|
// allocate worst case memory for the temporary vectors
|
||||||
vecChanIDsCurConChan.Init ( iMaxNumChannels );
|
vecChanIDsCurConChan.Init ( iMaxNumChannels );
|
||||||
|
vecvecdGains.Init ( iMaxNumChannels );
|
||||||
|
vecvecsData.Init ( iMaxNumChannels );
|
||||||
|
vecNumAudioChannels.Init ( iMaxNumChannels );
|
||||||
|
|
||||||
|
for ( i = 0; i < iMaxNumChannels; i++ )
|
||||||
|
{
|
||||||
|
// init vectors storing information of all channels
|
||||||
|
vecvecdGains[i].Init ( iMaxNumChannels );
|
||||||
|
|
||||||
|
// we always use stereo audio buffers (see "vecsSendData")
|
||||||
|
vecvecsData[i].Init ( 2 * SYSTEM_FRAME_SIZE_SAMPLES );
|
||||||
|
}
|
||||||
|
|
||||||
|
// allocate worst case memory for the coded data
|
||||||
|
vecbyCodedData.Init ( MAX_SIZE_BYTES_NETW_BUF );
|
||||||
|
|
||||||
|
|
||||||
// enable history graph (if requested)
|
// enable history graph (if requested)
|
||||||
if ( !strHistoryFileName.isEmpty() )
|
if ( !strHistoryFileName.isEmpty() )
|
||||||
|
@ -646,11 +669,6 @@ void CServer::OnTimer()
|
||||||
{
|
{
|
||||||
int i, j;
|
int i, j;
|
||||||
|
|
||||||
// TODO avoid allocating memory in the time critical processing routine
|
|
||||||
CVector<CVector<double> > vecvecdGains;
|
|
||||||
CVector<CVector<int16_t> > vecvecsData;
|
|
||||||
CVector<int> vecNumAudioChannels;
|
|
||||||
|
|
||||||
|
|
||||||
// Get data from all connected clients -------------------------------------
|
// Get data from all connected clients -------------------------------------
|
||||||
// some inits
|
// some inits
|
||||||
|
@ -675,18 +693,6 @@ CVector<int> vecNumAudioChannels;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// init temporary vectors
|
|
||||||
|
|
||||||
// TODO in the entire realtime timer routine including the ProcessData no
|
|
||||||
// memory must be allocated -> use member variables for the vectors and
|
|
||||||
// only change the size on changing the number of connected clients at
|
|
||||||
// the server
|
|
||||||
|
|
||||||
// TODO avoid allocating memory in the time critical processing routine
|
|
||||||
vecvecdGains.Init ( iNumClients );
|
|
||||||
vecvecsData.Init ( iNumClients );
|
|
||||||
vecNumAudioChannels.Init ( iNumClients );
|
|
||||||
|
|
||||||
// process connected channels
|
// process connected channels
|
||||||
for ( i = 0; i < iNumClients; i++ )
|
for ( i = 0; i < iNumClients; i++ )
|
||||||
{
|
{
|
||||||
|
@ -699,10 +705,6 @@ vecNumAudioChannels.Init ( iNumClients );
|
||||||
|
|
||||||
vecNumAudioChannels[i] = iCurNumAudChan;
|
vecNumAudioChannels[i] = iCurNumAudChan;
|
||||||
|
|
||||||
// init vectors storing information of all channels
|
|
||||||
vecvecdGains[i].Init ( iNumClients );
|
|
||||||
vecvecsData[i].Init ( iCurNumAudChan * SYSTEM_FRAME_SIZE_SAMPLES );
|
|
||||||
|
|
||||||
// get gains of all connected channels
|
// get gains of all connected channels
|
||||||
for ( j = 0; j < iNumClients; j++ )
|
for ( j = 0; j < iNumClients; j++ )
|
||||||
{
|
{
|
||||||
|
@ -718,13 +720,10 @@ vecNumAudioChannels.Init ( iNumClients );
|
||||||
const int iCeltNumCodedBytes =
|
const int iCeltNumCodedBytes =
|
||||||
vecChannels[iCurChanID].GetNetwFrameSize();
|
vecChannels[iCurChanID].GetNetwFrameSize();
|
||||||
|
|
||||||
// init temporal data vector and clear input buffers
|
|
||||||
// TODO avoid allocating memory in the time critical processing routine
|
|
||||||
CVector<uint8_t> vecbyData ( iCeltNumCodedBytes );
|
|
||||||
|
|
||||||
// get data
|
// get data
|
||||||
const EGetDataStat eGetStat =
|
const EGetDataStat eGetStat =
|
||||||
vecChannels[iCurChanID].GetData ( vecbyData );
|
vecChannels[iCurChanID].GetData ( vecbyCodedData,
|
||||||
|
iCeltNumCodedBytes );
|
||||||
|
|
||||||
// if channel was just disconnected, set flag that connected
|
// if channel was just disconnected, set flag that connected
|
||||||
// client list is sent to all other clients
|
// client list is sent to all other clients
|
||||||
|
@ -743,14 +742,14 @@ CVector<uint8_t> vecbyData ( iCeltNumCodedBytes );
|
||||||
if ( vecChannels[iCurChanID].GetAudioCompressionType() == CT_CELT )
|
if ( vecChannels[iCurChanID].GetAudioCompressionType() == CT_CELT )
|
||||||
{
|
{
|
||||||
cc6_celt_decode ( CeltDecoderMono[iCurChanID],
|
cc6_celt_decode ( CeltDecoderMono[iCurChanID],
|
||||||
&vecbyData[0],
|
&vecbyCodedData[0],
|
||||||
iCeltNumCodedBytes,
|
iCeltNumCodedBytes,
|
||||||
&vecvecsData[i][0] );
|
&vecvecsData[i][0] );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
opus_custom_decode ( OpusDecoderMono[iCurChanID],
|
opus_custom_decode ( OpusDecoderMono[iCurChanID],
|
||||||
&vecbyData[0],
|
&vecbyCodedData[0],
|
||||||
iCeltNumCodedBytes,
|
iCeltNumCodedBytes,
|
||||||
&vecvecsData[i][0],
|
&vecvecsData[i][0],
|
||||||
SYSTEM_FRAME_SIZE_SAMPLES );
|
SYSTEM_FRAME_SIZE_SAMPLES );
|
||||||
|
@ -763,14 +762,14 @@ CVector<uint8_t> vecbyData ( iCeltNumCodedBytes );
|
||||||
if ( vecChannels[iCurChanID].GetAudioCompressionType() == CT_CELT )
|
if ( vecChannels[iCurChanID].GetAudioCompressionType() == CT_CELT )
|
||||||
{
|
{
|
||||||
cc6_celt_decode ( CeltDecoderStereo[iCurChanID],
|
cc6_celt_decode ( CeltDecoderStereo[iCurChanID],
|
||||||
&vecbyData[0],
|
&vecbyCodedData[0],
|
||||||
iCeltNumCodedBytes,
|
iCeltNumCodedBytes,
|
||||||
&vecvecsData[i][0] );
|
&vecvecsData[i][0] );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
opus_custom_decode ( OpusDecoderStereo[iCurChanID],
|
opus_custom_decode ( OpusDecoderStereo[iCurChanID],
|
||||||
&vecbyData[0],
|
&vecbyCodedData[0],
|
||||||
iCeltNumCodedBytes,
|
iCeltNumCodedBytes,
|
||||||
&vecvecsData[i][0],
|
&vecvecsData[i][0],
|
||||||
SYSTEM_FRAME_SIZE_SAMPLES );
|
SYSTEM_FRAME_SIZE_SAMPLES );
|
||||||
|
@ -846,30 +845,20 @@ CVector<uint8_t> vecbyData ( iCeltNumCodedBytes );
|
||||||
// get number of audio channels of current channel
|
// get number of audio channels of current channel
|
||||||
const int iCurNumAudChan = vecNumAudioChannels[i];
|
const int iCurNumAudChan = vecNumAudioChannels[i];
|
||||||
|
|
||||||
// calculate the number of samples for output vector
|
|
||||||
const int iNumOutSamples =
|
|
||||||
iCurNumAudChan * SYSTEM_FRAME_SIZE_SAMPLES;
|
|
||||||
|
|
||||||
// allocate memory for the send data vector
|
|
||||||
// TODO avoid allocating memory in the time critical processing routine
|
|
||||||
CVector<int16_t> vecsSendData ( iNumOutSamples );
|
|
||||||
|
|
||||||
// generate a sparate mix for each channel
|
// generate a sparate mix for each channel
|
||||||
// actual processing of audio data -> mix
|
// actual processing of audio data -> mix
|
||||||
ProcessData ( iCurNumAudChan,
|
ProcessData ( vecvecsData,
|
||||||
vecvecsData,
|
|
||||||
vecvecdGains[i],
|
vecvecdGains[i],
|
||||||
vecNumAudioChannels,
|
vecNumAudioChannels,
|
||||||
vecsSendData );
|
vecsSendData,
|
||||||
|
iCurNumAudChan,
|
||||||
|
iNumClients );
|
||||||
|
|
||||||
// get current number of CELT coded bytes
|
// get current number of CELT coded bytes
|
||||||
const int iCeltNumCodedBytes =
|
const int iCeltNumCodedBytes =
|
||||||
vecChannels[iCurChanID].GetNetwFrameSize();
|
vecChannels[iCurChanID].GetNetwFrameSize();
|
||||||
|
|
||||||
// CELT encoding
|
// OPUS/CELT encoding
|
||||||
// TODO avoid allocating memory in the time critical processing routine
|
|
||||||
CVector<unsigned char> vecCeltData ( iCeltNumCodedBytes );
|
|
||||||
|
|
||||||
if ( vecChannels[iCurChanID].GetNumAudioChannels() == 1 )
|
if ( vecChannels[iCurChanID].GetNumAudioChannels() == 1 )
|
||||||
{
|
{
|
||||||
// mono:
|
// mono:
|
||||||
|
@ -879,7 +868,7 @@ CVector<unsigned char> vecCeltData ( iCeltNumCodedBytes );
|
||||||
cc6_celt_encode ( CeltEncoderMono[iCurChanID],
|
cc6_celt_encode ( CeltEncoderMono[iCurChanID],
|
||||||
&vecsSendData[0],
|
&vecsSendData[0],
|
||||||
NULL,
|
NULL,
|
||||||
&vecCeltData[0],
|
&vecbyCodedData[0],
|
||||||
iCeltNumCodedBytes );
|
iCeltNumCodedBytes );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -894,7 +883,7 @@ opus_custom_encoder_ctl ( OpusEncoderMono[iCurChanID],
|
||||||
opus_custom_encode ( OpusEncoderMono[iCurChanID],
|
opus_custom_encode ( OpusEncoderMono[iCurChanID],
|
||||||
&vecsSendData[0],
|
&vecsSendData[0],
|
||||||
SYSTEM_FRAME_SIZE_SAMPLES,
|
SYSTEM_FRAME_SIZE_SAMPLES,
|
||||||
&vecCeltData[0],
|
&vecbyCodedData[0],
|
||||||
iCeltNumCodedBytes );
|
iCeltNumCodedBytes );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -907,11 +896,12 @@ opus_custom_encoder_ctl ( OpusEncoderMono[iCurChanID],
|
||||||
cc6_celt_encode ( CeltEncoderStereo[iCurChanID],
|
cc6_celt_encode ( CeltEncoderStereo[iCurChanID],
|
||||||
&vecsSendData[0],
|
&vecsSendData[0],
|
||||||
NULL,
|
NULL,
|
||||||
&vecCeltData[0],
|
&vecbyCodedData[0],
|
||||||
iCeltNumCodedBytes );
|
iCeltNumCodedBytes );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
||||||
// TODO find a better place than this: the setting does not change all the time
|
// TODO find a better place than this: the setting does not change all the time
|
||||||
// so for speed optimization it would be better to set it only if the network
|
// so for speed optimization it would be better to set it only if the network
|
||||||
// frame size is changed
|
// frame size is changed
|
||||||
|
@ -921,13 +911,15 @@ opus_custom_encoder_ctl ( OpusEncoderStereo[iCurChanID],
|
||||||
opus_custom_encode ( OpusEncoderStereo[iCurChanID],
|
opus_custom_encode ( OpusEncoderStereo[iCurChanID],
|
||||||
&vecsSendData[0],
|
&vecsSendData[0],
|
||||||
SYSTEM_FRAME_SIZE_SAMPLES,
|
SYSTEM_FRAME_SIZE_SAMPLES,
|
||||||
&vecCeltData[0],
|
&vecbyCodedData[0],
|
||||||
iCeltNumCodedBytes );
|
iCeltNumCodedBytes );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// send separate mix to current clients
|
// send separate mix to current clients
|
||||||
vecChannels[iCurChanID].PrepAndSendPacket ( &Socket, vecCeltData );
|
vecChannels[iCurChanID].PrepAndSendPacket ( &Socket,
|
||||||
|
vecbyCodedData,
|
||||||
|
iCeltNumCodedBytes );
|
||||||
|
|
||||||
// update socket buffer size
|
// update socket buffer size
|
||||||
vecChannels[iCurChanID].UpdateSocketBufferSize();
|
vecChannels[iCurChanID].UpdateSocketBufferSize();
|
||||||
|
@ -942,17 +934,15 @@ opus_custom_encoder_ctl ( OpusEncoderStereo[iCurChanID],
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Mix all audio data from all clients together.
|
/// @brief Mix all audio data from all clients together.
|
||||||
void CServer::ProcessData ( const int iCurNumAudChan,
|
void CServer::ProcessData ( const CVector<CVector<int16_t> >& vecvecsData,
|
||||||
const CVector<CVector<int16_t> >& vecvecsData,
|
|
||||||
const CVector<double>& vecdGains,
|
const CVector<double>& vecdGains,
|
||||||
const CVector<int>& vecNumAudioChannels,
|
const CVector<int>& vecNumAudioChannels,
|
||||||
CVector<int16_t>& vecsOutData )
|
CVector<int16_t>& vecsOutData,
|
||||||
|
const int iCurNumAudChan,
|
||||||
|
const int iNumClients )
|
||||||
{
|
{
|
||||||
int i, j, k;
|
int i, j, k;
|
||||||
|
|
||||||
// get the number of clients
|
|
||||||
const int iNumClients = vecvecsData.Size();
|
|
||||||
|
|
||||||
// init return vector with zeros since we mix all channels on that vector
|
// init return vector with zeros since we mix all channels on that vector
|
||||||
vecsOutData.Reset ( 0 );
|
vecsOutData.Reset ( 0 );
|
||||||
|
|
||||||
|
|
65
src/server.h
65
src/server.h
|
@ -203,58 +203,65 @@ protected:
|
||||||
const QString& strChatText );
|
const QString& strChatText );
|
||||||
void WriteHTMLChannelList();
|
void WriteHTMLChannelList();
|
||||||
|
|
||||||
void ProcessData ( const int iCurNumAudChan,
|
void ProcessData ( const CVector<CVector<int16_t> >& vecvecsData,
|
||||||
const CVector<CVector<int16_t> >& vecvecsData,
|
|
||||||
const CVector<double>& vecdGains,
|
const CVector<double>& vecdGains,
|
||||||
const CVector<int>& vecNumAudioChannels,
|
const CVector<int>& vecNumAudioChannels,
|
||||||
CVector<int16_t>& vecsOutData );
|
CVector<int16_t>& vecsOutData,
|
||||||
|
const int iCurNumAudChan,
|
||||||
|
const int iNumClients );
|
||||||
|
|
||||||
virtual void customEvent ( QEvent* pEvent );
|
virtual void customEvent ( QEvent* pEvent );
|
||||||
|
|
||||||
// do not use the vector class since CChannel does not have appropriate
|
// do not use the vector class since CChannel does not have appropriate
|
||||||
// copy constructor/operator
|
// copy constructor/operator
|
||||||
CChannel vecChannels[MAX_NUM_CHANNELS];
|
CChannel vecChannels[MAX_NUM_CHANNELS];
|
||||||
int iMaxNumChannels;
|
int iMaxNumChannels;
|
||||||
CProtocol ConnLessProtocol;
|
CProtocol ConnLessProtocol;
|
||||||
QMutex Mutex;
|
QMutex Mutex;
|
||||||
|
|
||||||
// audio encoder/decoder
|
// audio encoder/decoder
|
||||||
cc6_CELTMode* CeltModeMono[MAX_NUM_CHANNELS];
|
cc6_CELTMode* CeltModeMono[MAX_NUM_CHANNELS];
|
||||||
cc6_CELTEncoder* CeltEncoderMono[MAX_NUM_CHANNELS];
|
cc6_CELTEncoder* CeltEncoderMono[MAX_NUM_CHANNELS];
|
||||||
cc6_CELTDecoder* CeltDecoderMono[MAX_NUM_CHANNELS];
|
cc6_CELTDecoder* CeltDecoderMono[MAX_NUM_CHANNELS];
|
||||||
cc6_CELTMode* CeltModeStereo[MAX_NUM_CHANNELS];
|
cc6_CELTMode* CeltModeStereo[MAX_NUM_CHANNELS];
|
||||||
cc6_CELTEncoder* CeltEncoderStereo[MAX_NUM_CHANNELS];
|
cc6_CELTEncoder* CeltEncoderStereo[MAX_NUM_CHANNELS];
|
||||||
cc6_CELTDecoder* CeltDecoderStereo[MAX_NUM_CHANNELS];
|
cc6_CELTDecoder* CeltDecoderStereo[MAX_NUM_CHANNELS];
|
||||||
OpusCustomMode* OpusMode[MAX_NUM_CHANNELS];
|
OpusCustomMode* OpusMode[MAX_NUM_CHANNELS];
|
||||||
OpusCustomEncoder* OpusEncoderMono[MAX_NUM_CHANNELS];
|
OpusCustomEncoder* OpusEncoderMono[MAX_NUM_CHANNELS];
|
||||||
OpusCustomDecoder* OpusDecoderMono[MAX_NUM_CHANNELS];
|
OpusCustomDecoder* OpusDecoderMono[MAX_NUM_CHANNELS];
|
||||||
OpusCustomEncoder* OpusEncoderStereo[MAX_NUM_CHANNELS];
|
OpusCustomEncoder* OpusEncoderStereo[MAX_NUM_CHANNELS];
|
||||||
OpusCustomDecoder* OpusDecoderStereo[MAX_NUM_CHANNELS];
|
OpusCustomDecoder* OpusDecoderStereo[MAX_NUM_CHANNELS];
|
||||||
|
|
||||||
CVector<QString> vstrChatColors;
|
CVector<QString> vstrChatColors;
|
||||||
CVector<int> vecChanIDsCurConChan;
|
CVector<int> vecChanIDsCurConChan;
|
||||||
|
|
||||||
|
CVector<CVector<double> > vecvecdGains;
|
||||||
|
CVector<CVector<int16_t> > vecvecsData;
|
||||||
|
CVector<int> vecNumAudioChannels;
|
||||||
|
CVector<int16_t> vecsSendData;
|
||||||
|
CVector<uint8_t> vecbyCodedData;
|
||||||
|
|
||||||
// actual working objects
|
// actual working objects
|
||||||
CSocket Socket;
|
CSocket Socket;
|
||||||
|
|
||||||
// logging
|
// logging
|
||||||
CServerLogging Logging;
|
CServerLogging Logging;
|
||||||
|
|
||||||
// HTML file server status
|
// HTML file server status
|
||||||
bool bWriteStatusHTMLFile;
|
bool bWriteStatusHTMLFile;
|
||||||
QString strServerHTMLFileListName;
|
QString strServerHTMLFileListName;
|
||||||
QString strServerNameWithPort;
|
QString strServerNameWithPort;
|
||||||
|
|
||||||
CHighPrecisionTimer HighPrecisionTimer;
|
CHighPrecisionTimer HighPrecisionTimer;
|
||||||
|
|
||||||
// server list
|
// server list
|
||||||
CServerListManager ServerListManager;
|
CServerListManager ServerListManager;
|
||||||
|
|
||||||
// GUI settings
|
// GUI settings
|
||||||
bool bAutoRunMinimized;
|
bool bAutoRunMinimized;
|
||||||
|
|
||||||
// messaging
|
// messaging
|
||||||
QString strWelcomeMessage;
|
QString strWelcomeMessage;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void Started();
|
void Started();
|
||||||
|
|
Loading…
Reference in a new issue