insert invalid elements when buffer underrun to improve PLC, some code clean up
This commit is contained in:
parent
130901ef39
commit
29f6684aba
1 changed files with 20 additions and 213 deletions
229
src/buffer.cpp
229
src/buffer.cpp
|
@ -37,12 +37,13 @@ void CNetBuf::Init ( const int iNewBlockSize,
|
|||
iBlockSize = iNewBlockSize;
|
||||
|
||||
// total size -> size of one block times the number of blocks
|
||||
CBufferBase<uint8_t>::Init ( iNewBlockSize * iNewNumBlocks, bPreserve );
|
||||
CBufferBase<uint8_t>::Init ( iNewBlockSize * iNewNumBlocks,
|
||||
bPreserve );
|
||||
|
||||
// use the "get" flag to make sure the buffer is cleared
|
||||
// clear buffer if not preserved
|
||||
if ( !bPreserve )
|
||||
{
|
||||
Clear ( CT_GET );
|
||||
Clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -51,47 +52,10 @@ bool CNetBuf::Put ( const CVector<uint8_t>& vecbyData,
|
|||
{
|
||||
bool bPutOK = true;
|
||||
|
||||
// Check if there is not enough space available -> correct
|
||||
// check if there is not enough space available
|
||||
if ( GetAvailSpace() < iInSize )
|
||||
{
|
||||
/*
|
||||
// not enough space in buffer for put operation, correct buffer to
|
||||
// prepare for new data
|
||||
Clear ( CT_PUT );
|
||||
|
||||
bPutOK = false; // return error flag
|
||||
*/
|
||||
|
||||
/*
|
||||
// TEST invalidate last written block for better PLC
|
||||
// ATTENTION: We assume that mem size is factor of block size here!!!!
|
||||
if ( !bIsSimulation )
|
||||
{
|
||||
if ( iPutPos == 0 )
|
||||
{
|
||||
for ( int iPos = iMemSize - iInSize; iPos < iMemSize; iPos++ )
|
||||
{
|
||||
vecMemory[iPos] = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for ( int iPos = iPutPos - iInSize; iPos < iPutPos; iPos++ )
|
||||
{
|
||||
vecMemory[iPos] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
return false;
|
||||
|
||||
// check for special case: buffer memory is not sufficient
|
||||
if ( iInSize > iMemSize )
|
||||
{
|
||||
// do nothing here, just return error code
|
||||
return bPutOK;
|
||||
}
|
||||
}
|
||||
|
||||
// copy new data in internal buffer (implemented in base class)
|
||||
|
@ -112,195 +76,38 @@ bool CNetBuf::Get ( CVector<uint8_t>& vecbyData )
|
|||
{
|
||||
return false;
|
||||
}
|
||||
/*
|
||||
|
||||
// check for invalid data in buffer
|
||||
if ( iNumInvalidElements > 0 )
|
||||
{
|
||||
// decrease number of invalid elements by the queried number (input
|
||||
// size)
|
||||
iNumInvalidElements -= iInSize;
|
||||
// decrease number of invalid elements by one
|
||||
iNumInvalidElements -= 1;
|
||||
|
||||
bGetOK = false; // return error flag
|
||||
// return error flag, do not return function here since we have
|
||||
// to call the base Get function to pick one block out of the
|
||||
// buffer
|
||||
bGetOK = false;
|
||||
}
|
||||
*/
|
||||
|
||||
// Check if there is not enough data available -> correct
|
||||
// check if there is not enough data available -> correct
|
||||
if ( GetAvailData() < iInSize )
|
||||
{
|
||||
/*
|
||||
// not enough data in buffer for get operation, correct buffer to
|
||||
// prepare for getting data
|
||||
Clear ( CT_GET );
|
||||
// in case we have a buffer underrun, invalidate the next 15 blocks
|
||||
// to avoid the unmusical noise resulting from a very short drop
|
||||
// out (note that if you want to change this value, also change
|
||||
// the value in celt_decode_lost in celt.c)
|
||||
iNumInvalidElements = 15;
|
||||
|
||||
bGetOK = false; // return error flag
|
||||
*/
|
||||
return false;
|
||||
|
||||
// check for special case: buffer memory is not sufficient
|
||||
if ( iInSize > iMemSize )
|
||||
{
|
||||
// do nothing here, just return error code
|
||||
return bGetOK;
|
||||
}
|
||||
}
|
||||
|
||||
// copy data from internal buffer in output buffer (implemented in base
|
||||
// class)
|
||||
CBufferBase<uint8_t>::Get ( vecbyData );
|
||||
|
||||
/*
|
||||
// TEST check for all zero packet
|
||||
bool bAllZeroPacket = true;
|
||||
for ( int iPos = 0; iPos < iInSize; iPos++ )
|
||||
{
|
||||
if ( vecbyData[iPos] != 0 )
|
||||
{
|
||||
bAllZeroPacket = false;
|
||||
}
|
||||
}
|
||||
if ( bAllZeroPacket )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
*/
|
||||
|
||||
return bGetOK;
|
||||
}
|
||||
|
||||
void CNetBuf::Clear ( const EClearType eClearType )
|
||||
{
|
||||
|
||||
// TEST
|
||||
CBufferBase<uint8_t>::Clear ( eClearType );
|
||||
|
||||
|
||||
/*
|
||||
// Define the number of blocks bound for the "random offset" (1) algorithm.
|
||||
// If we are above the bound, we use the "middle of buffer" (2) algorithm.
|
||||
//
|
||||
// Test results (with different jitter buffer sizes), given is the error
|
||||
// probability of jitter buffer (probability of corrections in the buffer):
|
||||
// kX, 128 samples, WLAN:
|
||||
// 2: (1) 5 %, (2) 12.3 %
|
||||
// 3: (1) 18.3 %, (2) 17.1 %
|
||||
// 5: (1) 0.9 %, (2) 0.8 %
|
||||
// kX, 128 samples, localhost:
|
||||
// 2: (1) 2.5 %, (2) 13 %
|
||||
// 3: (1) 0.9 %, (2) 1.1 %
|
||||
// 5: (1) 0.7 %, (2) 0.6 %
|
||||
// Behringer, 128 samples, WLAN:
|
||||
// 2: (1) 5.8 %, (2) 9.4 %
|
||||
// 3: (1) 0.9 %, (2) 0.8 %
|
||||
// 5: (1) 0.4 %, (2) 0.3 %
|
||||
// Behringer, 128 samples, localhost:
|
||||
// 2: (1) 1 %, (2) 9.8 %
|
||||
// 3: (1) 0.57 %, (2) 0.6 %
|
||||
// 5: (1) 0.6 %, (2) 0.56 %
|
||||
// kX, 256 samples, WLAN:
|
||||
// 3: (1) 24.2 %, (2) 18.4 %
|
||||
// 4: (1) 1.5 %, (2) 2.5 %
|
||||
// 5: (1) 1 %, (2) 1 %
|
||||
// ASIO4All, 256 samples, WLAN:
|
||||
// 3: (1) 14.9 %, (2) 11.9 %
|
||||
// 4: (1) 1.5 %, (2) 7 %
|
||||
// 5: (1) 1.2 %, (2) 1.3 %
|
||||
const int iNumBlocksBoundInclForRandom = 4; // by extensive testing: 4
|
||||
|
||||
int iNewFillLevel = 0;
|
||||
|
||||
if ( iBlockSize != 0 )
|
||||
{
|
||||
const int iNumBlocks = iMemSize / iBlockSize;
|
||||
if ( iNumBlocks <= iNumBlocksBoundInclForRandom ) // just for small buffers
|
||||
{
|
||||
// Random position algorithm.
|
||||
// overwrite fill level with random value, the range
|
||||
// is 0 to (iMemSize - iBlockSize)
|
||||
iNewFillLevel = static_cast<int> ( static_cast<double> ( rand() ) *
|
||||
iNumBlocks / RAND_MAX ) * iBlockSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Middle of buffer algorithm.
|
||||
// with the following operation we set the fill level to a block
|
||||
// boundary (one block below the middle of the buffer in case of odd
|
||||
// number of blocks, e.g.:
|
||||
// [buffer size]: [get pos]
|
||||
// 1: 0 / 2: 0 / 3: 1 / 4: 1 / 5: 2 ...)
|
||||
iNewFillLevel =
|
||||
( ( ( iMemSize - iBlockSize) / 2 ) / iBlockSize ) * iBlockSize;
|
||||
|
||||
|
||||
// TEST
|
||||
iNewFillLevel += static_cast<int> ( static_cast<double> ( rand() ) *
|
||||
iNumBlocksBoundInclForRandom / RAND_MAX ) * iBlockSize -
|
||||
iNumBlocksBoundInclForRandom / 2 * iBlockSize;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// different behaviour for get and put corrections
|
||||
if ( eClearType == CT_GET )
|
||||
{
|
||||
// clear buffer since we had a buffer underrun
|
||||
if ( !bIsSimulation )
|
||||
{
|
||||
vecMemory.Reset ( 0 );
|
||||
}
|
||||
|
||||
// reset buffer pointers so that they are at maximum distance after
|
||||
// the get operation (assign new fill level value to the get pointer)
|
||||
iPutPos = 0;
|
||||
iGetPos = iNewFillLevel;
|
||||
|
||||
// The buffer was cleared, the next time blocks are read from the
|
||||
// buffer, these are invalid ones. Calculate the number of invalid
|
||||
// elements
|
||||
iNumInvalidElements = iMemSize - iNewFillLevel;
|
||||
|
||||
// check for special case
|
||||
if ( iPutPos == iGetPos )
|
||||
{
|
||||
eBufState = CNetBuf::BS_FULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
eBufState = CNetBuf::BS_OK;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// in case of "put" correction, do not delete old data but only shift
|
||||
// the pointers
|
||||
iPutPos = iNewFillLevel;
|
||||
|
||||
// adjust put pointer relative to current get pointer, take care of
|
||||
// wrap around
|
||||
iPutPos += iGetPos;
|
||||
if ( iPutPos > iMemSize )
|
||||
{
|
||||
iPutPos -= iMemSize;
|
||||
}
|
||||
|
||||
// in case of put correction, no invalid blocks are inserted
|
||||
iNumInvalidElements = 0;
|
||||
|
||||
// check for special case
|
||||
if ( iPutPos == iGetPos )
|
||||
{
|
||||
eBufState = CNetBuf::BS_EMPTY;
|
||||
}
|
||||
else
|
||||
{
|
||||
eBufState = CNetBuf::BS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
// TEST
|
||||
//iNumInvalidElements = 8 * iMemSize;
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
/* Network buffer with statistic calculations implementation ******************/
|
||||
CNetBufWithStats::CNetBufWithStats() :
|
||||
|
|
Loading…
Reference in a new issue