From 036d8b3d2d095cb67c9afff3f201b4233ed53f4a Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Wed, 22 Nov 2017 13:21:48 +0000 Subject: [PATCH] Beginnings of a generic jitter buffer for all modes. --- JitterBuffer.cpp | 127 ++++++++++++++++++++++++++++++++++++++ JitterBuffer.h | 62 +++++++++++++++++++ MMDVMHost.vcxproj | 2 + MMDVMHost.vcxproj.filters | 6 ++ Makefile | 6 +- Makefile.Pi | 6 +- Makefile.Pi.Adafruit | 6 +- Makefile.Pi.HD44780 | 6 +- Makefile.Pi.OLED | 6 +- Makefile.Pi.PCF8574 | 6 +- Makefile.Solaris | 6 +- 11 files changed, 218 insertions(+), 21 deletions(-) create mode 100644 JitterBuffer.cpp create mode 100644 JitterBuffer.h diff --git a/JitterBuffer.cpp b/JitterBuffer.cpp new file mode 100644 index 0000000..17d6cc5 --- /dev/null +++ b/JitterBuffer.cpp @@ -0,0 +1,127 @@ +/* +* Copyright (C) 2017 by Jonathan Naylor G4KLX +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "JitterBuffer.h" + +#include +#include + +CJitterBuffer::CJitterBuffer(unsigned int blockSize, unsigned int blockTime, unsigned int jitterTime, unsigned int topSequenceNumber) : +m_blockSize(blockSize), +m_blockTime(blockTime), +m_topSequenceNumber(topSequenceNumber), +m_blockCount(0U), +m_timer(1000U, 0U, jitterTime), +m_stopWatch(), +m_buffer(NULL), +m_headSequenceNumber(0U) +{ + assert(blockSize > 0U); + assert(blockTime > 0U); + assert(jitterTime > 0U); + assert(topSequenceNumber > 0U); + + m_blockCount = jitterTime / blockTime + 1U; + + m_buffer = new JitterEntry[m_blockCount]; + + for (unsigned int i = 0U; i < m_blockCount; i++) + m_buffer[i].m_data = new unsigned char[m_blockSize]; + + reset(); +} + +CJitterBuffer::~CJitterBuffer() +{ + for (unsigned int i = 0U; i < m_blockCount; i++) + delete[] m_buffer[i].m_data; + + delete[] m_buffer; +} + +bool CJitterBuffer::addData(const unsigned char* data, unsigned int sequenceNumber) +{ + assert(data != NULL); + + unsigned int headSequenceNumber = m_headSequenceNumber % m_topSequenceNumber; + unsigned int tailSequenceNumber = (m_headSequenceNumber + m_blockCount) % m_topSequenceNumber; + + // Is the data out of sequence? + if (headSequenceNumber < tailSequenceNumber) { + if (sequenceNumber < headSequenceNumber || sequenceNumber >= tailSequenceNumber) + return false; + } else { + if (sequenceNumber >= tailSequenceNumber && sequenceNumber < headSequenceNumber) + return false; + } + + unsigned int number = sequenceNumber - headSequenceNumber; + + // Do we already have the data? + if (m_buffer[number].m_used) + return false; + + ::memcpy(m_buffer[number].m_data, data, m_blockSize); + m_buffer[number].m_used = true; + + if (!m_timer.isRunning()) + m_timer.start(); + + return true; +} + +JB_STATUS CJitterBuffer::getData(unsigned char* data) +{ + assert(data != NULL); + + if (!m_timer.isRunning() || !m_timer.hasExpired()) { + m_stopWatch.start(); + return JBS_NO_DATA; + } + + unsigned int sequenceNumber = m_stopWatch.elapsed() / m_blockTime; + if (m_headSequenceNumber > sequenceNumber) + return JBS_NO_DATA; + + if (m_buffer[m_headSequenceNumber].m_used) { + ::memcpy(data, m_buffer[m_headSequenceNumber].m_data, m_blockSize); + + m_headSequenceNumber++; + + return JBS_DATA; + } + + m_headSequenceNumber++; + + return JBS_REPEAT; +} + +void CJitterBuffer::reset() +{ + for (unsigned int i = 0U; i < m_blockCount; i++) + m_buffer[i].m_used = false; + + m_headSequenceNumber = 0U; + + m_timer.stop(); +} + +void CJitterBuffer::clock(unsigned int ms) +{ + m_timer.clock(ms); +} diff --git a/JitterBuffer.h b/JitterBuffer.h new file mode 100644 index 0000000..951e8c0 --- /dev/null +++ b/JitterBuffer.h @@ -0,0 +1,62 @@ +/* +* Copyright (C) 2017 by Jonathan Naylor G4KLX +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#if !defined(JITTERBUFFER_H) +#define JITTERBUFFER_H + +#include "StopWatch.h" +#include "Timer.h" + +enum JB_STATUS { + JBS_NO_DATA, + JBS_DATA, + JBS_REPEAT +}; + +class CJitterBuffer { +public: + CJitterBuffer(unsigned int blockSize, unsigned int blockTime, unsigned int jitterTime, unsigned int topSequenceNumber); + ~CJitterBuffer(); + + bool addData(const unsigned char* data, unsigned int sequenceNumber); + + JB_STATUS getData(unsigned char* data); + + void reset(); + + void clock(unsigned int ms); + +private: + unsigned int m_blockSize; + unsigned int m_blockTime; + unsigned int m_topSequenceNumber; + unsigned int m_blockCount; + CTimer m_timer; + CStopWatch m_stopWatch; + + struct JitterEntry + { + unsigned char* m_data; + bool m_used; + }; + + JitterEntry* m_buffer; + unsigned int m_headSequenceNumber; +}; + +#endif diff --git a/MMDVMHost.vcxproj b/MMDVMHost.vcxproj index 5d575e0..2ca0a02 100644 --- a/MMDVMHost.vcxproj +++ b/MMDVMHost.vcxproj @@ -183,6 +183,7 @@ + @@ -253,6 +254,7 @@ + diff --git a/MMDVMHost.vcxproj.filters b/MMDVMHost.vcxproj.filters index 6373a8c..7fb37a0 100644 --- a/MMDVMHost.vcxproj.filters +++ b/MMDVMHost.vcxproj.filters @@ -224,6 +224,9 @@ Header Files + + Header Files + @@ -418,5 +421,8 @@ Source Files + + Source Files + \ No newline at end of file diff --git a/Makefile b/Makefile index f963f70..ee54b3e 100644 --- a/Makefile +++ b/Makefile @@ -9,9 +9,9 @@ LDFLAGS = -g OBJECTS = \ AMBEFEC.o BCH.o BPTC19696.o Conf.o CRC.o Display.o DMRControl.o DMRCSBK.o DMRData.o DMRDataHeader.o DMREMB.o DMREmbeddedData.o DMRFullLC.o DMRLookup.o DMRLC.o \ DMRNetwork.o DMRShortLC.o DMRSlot.o DMRSlotType.o DMRAccessControl.o DMRTrellis.o DStarControl.o DStarHeader.o DStarNetwork.o DStarSlowData.o Golay2087.o \ - Golay24128.o Hamming.o LCDproc.o Log.o MMDVMHost.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullDisplay.o P25Audio.o P25Control.o P25Data.o \ - P25LowSpeedData.o P25Network.o P25NID.o P25Utils.o QR1676.o RS129.o RS241213.o RSSIInterpolator.o SerialController.o SerialPort.o SHA256.o StopWatch.o Sync.o \ - TFTSerial.o Thread.o Timer.o UDPSocket.o UMP.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o + Golay24128.o Hamming.o JitterBuffer.o LCDproc.o Log.o MMDVMHost.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullDisplay.o P25Audio.o P25Control.o \ + P25Data.o P25LowSpeedData.o P25Network.o P25NID.o P25Utils.o QR1676.o RS129.o RS241213.o RSSIInterpolator.o SerialController.o SerialPort.o SHA256.o StopWatch.o \ + Sync.o TFTSerial.o Thread.o Timer.o UDPSocket.o UMP.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o all: MMDVMHost diff --git a/Makefile.Pi b/Makefile.Pi index f7b91cc..cfe8074 100644 --- a/Makefile.Pi +++ b/Makefile.Pi @@ -9,9 +9,9 @@ LDFLAGS = -g -L/usr/local/lib OBJECTS = \ AMBEFEC.o BCH.o BPTC19696.o Conf.o CRC.o Display.o DMRControl.o DMRCSBK.o DMRData.o DMRDataHeader.o DMREMB.o DMREmbeddedData.o DMRFullLC.o DMRLookup.o DMRLC.o \ DMRNetwork.o DMRShortLC.o DMRSlot.o DMRSlotType.o DMRAccessControl.o DMRTrellis.o DStarControl.o DStarHeader.o DStarNetwork.o DStarSlowData.o Golay2087.o \ - Golay24128.o Hamming.o LCDproc.o Log.o MMDVMHost.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullDisplay.o P25Audio.o P25Control.o P25Data.o \ - P25LowSpeedData.o P25Network.o P25NID.o P25Utils.o QR1676.o RS129.o RS241213.o RSSIInterpolator.o SerialController.o SerialPort.o SHA256.o StopWatch.o Sync.o \ - TFTSerial.o Thread.o Timer.o UDPSocket.o UMP.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o + Golay24128.o Hamming.o JitterBuffer.o LCDproc.o Log.o MMDVMHost.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullDisplay.o P25Audio.o P25Control.o \ + P25Data.o P25LowSpeedData.o P25Network.o P25NID.o P25Utils.o QR1676.o RS129.o RS241213.o RSSIInterpolator.o SerialController.o SerialPort.o SHA256.o StopWatch.o \ + Sync.o TFTSerial.o Thread.o Timer.o UDPSocket.o UMP.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o all: MMDVMHost diff --git a/Makefile.Pi.Adafruit b/Makefile.Pi.Adafruit index 13caba4..707c362 100644 --- a/Makefile.Pi.Adafruit +++ b/Makefile.Pi.Adafruit @@ -9,9 +9,9 @@ LDFLAGS = -g -L/usr/local/lib OBJECTS = \ AMBEFEC.o BCH.o BPTC19696.o Conf.o CRC.o Display.o DMRControl.o DMRCSBK.o DMRData.o DMRDataHeader.o DMREMB.o DMREmbeddedData.o DMRFullLC.o DMRLookup.o DMRLC.o \ DMRNetwork.o DMRShortLC.o DMRSlot.o DMRSlotType.o DMRAccessControl.o DMRTrellis.o DStarControl.o DStarHeader.o DStarNetwork.o DStarSlowData.o Golay2087.o \ - Golay24128.o Hamming.o HD44780.o LCDproc.o Log.o MMDVMHost.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullDisplay.o P25Audio.o P25Control.o \ - P25Data.o P25LowSpeedData.o P25Network.o P25NID.o P25Utils.o QR1676.o RS129.o RS241213.o RSSIInterpolator.o SerialController.o SerialPort.o SHA256.o StopWatch.o \ - Sync.o TFTSerial.o Thread.o Timer.o UDPSocket.o UMP.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o + Golay24128.o Hamming.o HD44780.o JitterBuffer.o LCDproc.o Log.o MMDVMHost.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullDisplay.o P25Audio.o \ + P25Control.o P25Data.o P25LowSpeedData.o P25Network.o P25NID.o P25Utils.o QR1676.o RS129.o RS241213.o RSSIInterpolator.o SerialController.o SerialPort.o SHA256.o \ + StopWatch.o Sync.o TFTSerial.o Thread.o Timer.o UDPSocket.o UMP.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o all: MMDVMHost diff --git a/Makefile.Pi.HD44780 b/Makefile.Pi.HD44780 index 3720b25..857c941 100644 --- a/Makefile.Pi.HD44780 +++ b/Makefile.Pi.HD44780 @@ -9,9 +9,9 @@ LDFLAGS = -g -L/usr/local/lib OBJECTS = \ AMBEFEC.o BCH.o BPTC19696.o Conf.o CRC.o Display.o DMRControl.o DMRCSBK.o DMRData.o DMRDataHeader.o DMREMB.o DMREmbeddedData.o DMRFullLC.o DMRLookup.o DMRLC.o \ DMRNetwork.o DMRShortLC.o DMRSlot.o DMRSlotType.o DMRAccessControl.o DMRTrellis.o DStarControl.o DStarHeader.o DStarNetwork.o DStarSlowData.o Golay2087.o \ - Golay24128.o Hamming.o HD44780.o LCDproc.o Log.o MMDVMHost.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullDisplay.o P25Audio.o P25Control.o \ - P25Data.o P25LowSpeedData.o P25Network.o P25NID.o P25Utils.o QR1676.o RS129.o RS241213.o RSSIInterpolator.o SerialController.o SerialPort.o SHA256.o StopWatch.o \ - Sync.o TFTSerial.o Thread.o Timer.o UDPSocket.o UMP.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o + Golay24128.o Hamming.o HD44780.o JitterBuffer.o LCDproc.o Log.o MMDVMHost.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullDisplay.o P25Audio.o \ + P25Control.o P25Data.o P25LowSpeedData.o P25Network.o P25NID.o P25Utils.o QR1676.o RS129.o RS241213.o RSSIInterpolator.o SerialController.o SerialPort.o SHA256.o \ + StopWatch.o Sync.o TFTSerial.o Thread.o Timer.o UDPSocket.o UMP.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o all: MMDVMHost diff --git a/Makefile.Pi.OLED b/Makefile.Pi.OLED index bb03e91..89731ae 100644 --- a/Makefile.Pi.OLED +++ b/Makefile.Pi.OLED @@ -9,9 +9,9 @@ LDFLAGS = -g -L/usr/local/lib OBJECTS = \ AMBEFEC.o BCH.o BPTC19696.o Conf.o CRC.o Display.o DMRControl.o DMRCSBK.o DMRData.o DMRDataHeader.o DMREMB.o DMREmbeddedData.o DMRFullLC.o DMRLookup.o DMRLC.o \ DMRNetwork.o DMRShortLC.o DMRSlot.o DMRSlotType.o DMRAccessControl.o DMRTrellis.o DStarControl.o DStarHeader.o DStarNetwork.o DStarSlowData.o Golay2087.o \ - Golay24128.o Hamming.o OLED.o LCDproc.o Log.o MMDVMHost.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullDisplay.o P25Audio.o P25Control.o P25Data.o \ - P25LowSpeedData.o P25Network.o P25NID.o P25Utils.o QR1676.o RS129.o RS241213.o RSSIInterpolator.o SerialController.o SerialPort.o SHA256.o StopWatch.o Sync.o \ - TFTSerial.o Thread.o Timer.o UDPSocket.o UMP.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o + Golay24128.o Hamming.o JitterBuffer.o OLED.o LCDproc.o Log.o MMDVMHost.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullDisplay.o P25Audio.o \ + P25Control.o P25Data.o P25LowSpeedData.o P25Network.o P25NID.o P25Utils.o QR1676.o RS129.o RS241213.o RSSIInterpolator.o SerialController.o SerialPort.o \ + SHA256.o StopWatch.o Sync.o TFTSerial.o Thread.o Timer.o UDPSocket.o UMP.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o all: MMDVMHost diff --git a/Makefile.Pi.PCF8574 b/Makefile.Pi.PCF8574 index b9104f4..56c7d34 100644 --- a/Makefile.Pi.PCF8574 +++ b/Makefile.Pi.PCF8574 @@ -9,9 +9,9 @@ LDFLAGS = -g -L/usr/local/lib OBJECTS = \ AMBEFEC.o BCH.o BPTC19696.o Conf.o CRC.o Display.o DMRControl.o DMRCSBK.o DMRData.o DMRDataHeader.o DMREMB.o DMREmbeddedData.o DMRFullLC.o DMRLookup.o DMRLC.o \ DMRNetwork.o DMRShortLC.o DMRSlot.o DMRSlotType.o DMRAccessControl.o DMRTrellis.o DStarControl.o DStarHeader.o DStarNetwork.o DStarSlowData.o Golay2087.o \ - Golay24128.o Hamming.o HD44780.o LCDproc.o Log.o MMDVMHost.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullDisplay.o P25Audio.o P25Control.o \ - P25Data.o P25LowSpeedData.o P25Network.o P25NID.o P25Utils.o QR1676.o RS129.o RS241213.o RSSIInterpolator.o SerialController.o SerialPort.o SHA256.o StopWatch.o \ - Sync.o TFTSerial.o Thread.o Timer.o UDPSocket.o UMP.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o + Golay24128.o Hamming.o HD44780.o JitterBuffer.o LCDproc.o Log.o MMDVMHost.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullDisplay.o P25Audio.o \ + P25Control.o P25Data.o P25LowSpeedData.o P25Network.o P25NID.o P25Utils.o QR1676.o RS129.o RS241213.o RSSIInterpolator.o SerialController.o SerialPort.o SHA256.o \ + StopWatch.o Sync.o TFTSerial.o Thread.o Timer.o UDPSocket.o UMP.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o all: MMDVMHost diff --git a/Makefile.Solaris b/Makefile.Solaris index dbfc33f..ad14d09 100644 --- a/Makefile.Solaris +++ b/Makefile.Solaris @@ -9,9 +9,9 @@ LDFLAGS = -g OBJECTS = \ AMBEFEC.o BCH.o BPTC19696.o Conf.o CRC.o Display.o DMRControl.o DMRCSBK.o DMRData.o DMRDataHeader.o DMREMB.o DMREmbeddedData.o DMRFullLC.o DMRLookup.o DMRLC.o \ DMRNetwork.o DMRShortLC.o DMRSlot.o DMRSlotType.o DMRAccessControl.o DMRTrellis.o DStarControl.o DStarHeader.o DStarNetwork.o DStarSlowData.o Golay2087.o \ - Golay24128.o Hamming.o LCDproc.o Log.o MMDVMHost.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullDisplay.o P25Audio.o P25Control.o P25Data.o \ - P25LowSpeedData.o P25Network.o P25NID.o P25Utils.o QR1676.o RS129.o RS241213.o RSSIInterpolator.o SerialController.o SerialPort.o SHA256.o StopWatch.o Sync.o \ - TFTSerial.o Thread.o Timer.o UDPSocket.o UMP.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o + Golay24128.o Hamming.o JitterBuffer.o LCDproc.o Log.o MMDVMHost.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullDisplay.o P25Audio.o P25Control.o \ + P25Data.o P25LowSpeedData.o P25Network.o P25NID.o P25Utils.o QR1676.o RS129.o RS241213.o RSSIInterpolator.o SerialController.o SerialPort.o SHA256.o StopWatch.o \ + Sync.o TFTSerial.o Thread.o Timer.o UDPSocket.o UMP.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o all: MMDVMHost