Update to the latest jitter buffer for compilation issues.

This commit is contained in:
Jonathan Naylor 2017-11-28 11:56:23 +00:00
parent 71bd38f9e9
commit a40826dd44
2 changed files with 72 additions and 36 deletions

View file

@ -18,27 +18,32 @@
#include "JitterBuffer.h" #include "JitterBuffer.h"
#include "Log.h"
#include <cstdio> #include <cstdio>
#include <cassert> #include <cassert>
#include <cstring>
CJitterBuffer::CJitterBuffer(unsigned int blockSize, unsigned int blockTime, unsigned int jitterTime, unsigned int topSequenceNumber) : CJitterBuffer::CJitterBuffer(unsigned int blockSize, unsigned int blockTime, unsigned int jitterTime, unsigned int topSequenceNumber, bool debug) :
m_blockSize(blockSize), m_blockSize(blockSize),
m_blockTime(blockTime), m_blockTime(blockTime),
m_topSequenceNumber(topSequenceNumber), m_topSequenceNumber(topSequenceNumber),
m_debug(debug),
m_blockCount(0U), m_blockCount(0U),
m_timer(1000U, 0U, jitterTime), m_timer(1000U, 0U, jitterTime),
m_stopWatch(), m_stopWatch(),
m_buffer(NULL), m_buffer(NULL),
m_headSequenceNumber(0U), m_headSequenceNumber(0U),
m_lastData(NULL), m_lastData(NULL),
m_lastDataValid(false) m_lastDataLength(0U),
m_running(false)
{ {
assert(blockSize > 0U); assert(blockSize > 0U);
assert(blockTime > 0U); assert(blockTime > 0U);
assert(jitterTime > 0U); assert(jitterTime > 0U);
assert(topSequenceNumber > 0U); assert(topSequenceNumber > 0U);
m_blockCount = jitterTime / blockTime + 1U; m_blockCount = (jitterTime / blockTime) * 2U + 1U;
m_buffer = new JitterEntry[m_blockCount]; m_buffer = new JitterEntry[m_blockCount];
@ -59,20 +64,28 @@ CJitterBuffer::~CJitterBuffer()
delete[] m_lastData; delete[] m_lastData;
} }
bool CJitterBuffer::addData(const unsigned char* data, unsigned int sequenceNumber) bool CJitterBuffer::addData(const unsigned char* data, unsigned int length, unsigned int sequenceNumber)
{ {
assert(data != NULL); assert(data != NULL);
assert(length > 0U);
assert(length <= m_blockSize);
unsigned int headSequenceNumber = m_headSequenceNumber % m_topSequenceNumber; unsigned int headSequenceNumber = m_headSequenceNumber % m_topSequenceNumber;
unsigned int tailSequenceNumber = (m_headSequenceNumber + m_blockCount) % m_topSequenceNumber; unsigned int tailSequenceNumber = (m_headSequenceNumber + m_blockCount) % m_topSequenceNumber;
// Is the data out of sequence? // Is the data out of sequence?
if (headSequenceNumber < tailSequenceNumber) { if (headSequenceNumber < tailSequenceNumber) {
if (sequenceNumber < headSequenceNumber || sequenceNumber >= tailSequenceNumber) if (sequenceNumber < headSequenceNumber || sequenceNumber >= tailSequenceNumber) {
if (m_debug)
LogDebug("JitterBuffer: rejecting frame with seqNo=%u, raw=%u, head=%u, tail=%u", sequenceNumber, m_headSequenceNumber, headSequenceNumber, tailSequenceNumber);
return false; return false;
}
} else { } else {
if (sequenceNumber >= tailSequenceNumber && sequenceNumber < headSequenceNumber) if (sequenceNumber >= tailSequenceNumber && sequenceNumber < headSequenceNumber) {
if (m_debug)
LogDebug("JitterBuffer: rejecting frame with seqNo=%u, raw=%u, head=%u, tail=%u", sequenceNumber, m_headSequenceNumber, headSequenceNumber, tailSequenceNumber);
return false; return false;
}
} }
unsigned int number; unsigned int number;
@ -84,70 +97,91 @@ bool CJitterBuffer::addData(const unsigned char* data, unsigned int sequenceNumb
unsigned int index = (m_headSequenceNumber + number) % m_blockCount; unsigned int index = (m_headSequenceNumber + number) % m_blockCount;
// Do we already have the data? // Do we already have the data?
if (m_buffer[index].m_used) if (m_buffer[index].m_length > 0U) {
if (m_debug)
LogDebug("JitterBuffer: rejecting duplicate frame with seqNo=%u, raw=%u, head=%u, tail=%u", sequenceNumber, m_headSequenceNumber, headSequenceNumber, tailSequenceNumber);
return false; return false;
}
::memcpy(m_buffer[index].m_data, data, m_blockSize); LogDebug("JitterBuffer: adding frame with seqNo=%u, raw=%u, head=%u, tail=%u", sequenceNumber, m_headSequenceNumber, headSequenceNumber, tailSequenceNumber);
m_buffer[index].m_used = true;
if (!m_timer.isRunning()) ::memcpy(m_buffer[index].m_data, data, length);
m_buffer[index].m_length = length;
if (!m_timer.isRunning()) {
LogDebug("JitterBuffer: starting the timer");
m_timer.start(); m_timer.start();
}
return true; return true;
} }
JB_STATUS CJitterBuffer::getData(unsigned char* data) JB_STATUS CJitterBuffer::getData(unsigned char* data, unsigned int& length)
{ {
assert(data != NULL); assert(data != NULL);
if (!m_timer.isRunning() || !m_timer.hasExpired()) { if (!m_running)
m_stopWatch.start();
return JBS_NO_DATA; return JBS_NO_DATA;
}
unsigned int sequenceNumber = m_stopWatch.elapsed() / m_blockTime; unsigned int sequenceNumber = m_stopWatch.elapsed() / m_blockTime + 3U;
if (m_headSequenceNumber > sequenceNumber) if (m_headSequenceNumber > sequenceNumber)
return JBS_NO_DATA; return JBS_NO_DATA;
unsigned int head = m_headSequenceNumber % m_blockCount; unsigned int head = m_headSequenceNumber % m_blockCount;
if (m_buffer[head].m_used) { m_headSequenceNumber++;
::memcpy(data, m_buffer[head].m_data, m_blockSize);
m_buffer[head].m_used = false; if (m_buffer[head].m_length > 0U) {
LogDebug("JitterBuffer: returning data, elapsed=%ums, raw=%u, head=%u", m_stopWatch.elapsed(), m_headSequenceNumber - 1U, head);
::memcpy(data, m_buffer[head].m_data, m_buffer[head].m_length);
length = m_buffer[head].m_length;
// Save this data in case no more data is available next time // Save this data in case no more data is available next time
::memcpy(m_lastData, m_buffer[head].m_data, m_blockSize); ::memcpy(m_lastData, m_buffer[head].m_data, m_buffer[head].m_length);
m_lastDataValid = true; m_lastDataLength = m_buffer[head].m_length;
m_headSequenceNumber++; m_buffer[head].m_length = 0U;
return JBS_DATA; return JBS_DATA;
} }
// Return the last data frame or null data if none exists if (m_debug)
if (m_lastDataValid) LogDebug("JitterBuffer: no data available, elapsed=%ums, raw=%u, head=%u", m_stopWatch.elapsed(), m_headSequenceNumber - 1U, head);
::memcpy(data, m_lastData, m_blockSize);
else
::memset(data, 0x00U, m_blockSize);
m_headSequenceNumber++; // Return the last data frame if we have it
if (m_lastDataLength > 0U) {
LogDebug("JitterBuffer: returning the last received frame");
::memcpy(data, m_lastData, m_lastDataLength);
length = m_lastDataLength;
return JBS_MISSING; return JBS_MISSING;
}
return JBS_NO_DATA;
} }
void CJitterBuffer::reset() void CJitterBuffer::reset()
{ {
for (unsigned int i = 0U; i < m_blockCount; i++) for (unsigned int i = 0U; i < m_blockCount; i++)
m_buffer[i].m_used = false; m_buffer[i].m_length = 0U;
m_headSequenceNumber = 0U; m_headSequenceNumber = 0U;
m_lastDataValid = false; m_lastDataLength = 0U;
m_timer.stop(); m_timer.stop();
m_running = false;
} }
void CJitterBuffer::clock(unsigned int ms) void CJitterBuffer::clock(unsigned int ms)
{ {
m_timer.clock(ms); m_timer.clock(ms);
if (m_timer.isRunning() && m_timer.hasExpired()) {
if (!m_running) {
m_stopWatch.start();
m_running = true;
}
}
} }

View file

@ -30,12 +30,12 @@ enum JB_STATUS {
class CJitterBuffer { class CJitterBuffer {
public: public:
CJitterBuffer(unsigned int blockSize, unsigned int blockTime, unsigned int jitterTime, unsigned int topSequenceNumber); CJitterBuffer(unsigned int blockSize, unsigned int blockTime, unsigned int jitterTime, unsigned int topSequenceNumber, bool debug);
~CJitterBuffer(); ~CJitterBuffer();
bool addData(const unsigned char* data, unsigned int sequenceNumber); bool addData(const unsigned char* data, unsigned int length, unsigned int sequenceNumber);
JB_STATUS getData(unsigned char* data); JB_STATUS getData(unsigned char* data, unsigned int& length);
void reset(); void reset();
@ -45,21 +45,23 @@ private:
unsigned int m_blockSize; unsigned int m_blockSize;
unsigned int m_blockTime; unsigned int m_blockTime;
unsigned int m_topSequenceNumber; unsigned int m_topSequenceNumber;
bool m_debug;
unsigned int m_blockCount; unsigned int m_blockCount;
CTimer m_timer; CTimer m_timer;
CStopWatch m_stopWatch; CStopWatch m_stopWatch;
bool m_running;
struct JitterEntry struct JitterEntry
{ {
unsigned char* m_data; unsigned char* m_data;
bool m_used; unsigned int m_length;
}; };
JitterEntry* m_buffer; JitterEntry* m_buffer;
unsigned int m_headSequenceNumber; unsigned int m_headSequenceNumber;
unsigned char* m_lastData; unsigned char* m_lastData;
bool m_lastDataValid; unsigned int m_lastDataLength;
}; };
#endif #endif