From 33a196e4aad3bad11a0e2cb79584ec3d93e985da Mon Sep 17 00:00:00 2001 From: f4exb Date: Sat, 20 Feb 2016 03:41:20 +0100 Subject: [PATCH] SDRdaemon plugin: fixed buffer issues --- .../sdrdaemon/sdrdaemonbuffer.cpp | 101 +++++++++--------- .../samplesource/sdrdaemon/sdrdaemonbuffer.h | 16 +-- .../sdrdaemon/sdrdaemonudphandler.cpp | 26 ++--- .../sdrdaemon/sdrdaemonudphandler.h | 3 - 4 files changed, 65 insertions(+), 81 deletions(-) diff --git a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp index f8afe5e8d..75630fcbe 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp +++ b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp @@ -16,11 +16,15 @@ #include #include +#include #include #include "sdrdaemonbuffer.h" -SDRdaemonBuffer::SDRdaemonBuffer(uint32_t blockSize, uint32_t rateDivider) : - m_blockSize(blockSize), +const int SDRdaemonBuffer::m_udpPayloadSize = 512; +const int SDRdaemonBuffer::m_sampleSize = 2; +const int SDRdaemonBuffer::m_iqSampleSize = 2 * m_sampleSize; + +SDRdaemonBuffer::SDRdaemonBuffer(uint32_t rateDivider) : m_rateDivider(rateDivider), m_sync(false), m_lz4(false), @@ -37,11 +41,10 @@ SDRdaemonBuffer::SDRdaemonBuffer(uint32_t blockSize, uint32_t rateDivider) : m_sampleRate(1000000), m_sampleBytes(2), m_sampleBits(12), - m_writeCount(0), - m_readCount(0), + m_writeIndex(0), + m_readChunkIndex(0), m_rawSize(0), m_rawBuffer(0), - m_chunkBuffer(0), m_bytesInBlock(0), m_nbBlocks(0) { @@ -61,10 +64,6 @@ SDRdaemonBuffer::~SDRdaemonBuffer() if (m_lz4OutBuffer) { delete[] m_lz4OutBuffer; } - - if (m_chunkBuffer) { - delete[] m_chunkBuffer; - } } bool SDRdaemonBuffer::readMeta(char *array, uint32_t length) @@ -87,10 +86,10 @@ bool SDRdaemonBuffer::readMeta(char *array, uint32_t length) m_currentMeta = *metaData; // sanity checks - if (metaData->m_blockSize == m_blockSize) // sent blocksize matches given blocksize + if (metaData->m_blockSize == m_udpPayloadSize) // sent blocksize matches given blocksize { m_sampleBytes = metaData->m_sampleBytes & 0x0F; - uint32_t frameSize = 2 * 2 * metaData->m_nbSamples * metaData->m_nbBlocks; + uint32_t frameSize = m_iqSampleSize * metaData->m_nbSamples * metaData->m_nbBlocks; uint32_t sampleRate = metaData->m_sampleRate; if (metaData->m_sampleBytes & 0x10) @@ -109,9 +108,9 @@ bool SDRdaemonBuffer::readMeta(char *array, uint32_t length) m_lz4 = false; } - if (frameSize != m_frameSize) + if (sampleRate != m_sampleRate) { - updateBufferSize(sampleRate, frameSize); + updateBufferSize(sampleRate); } m_sampleRate = sampleRate; @@ -182,7 +181,7 @@ void SDRdaemonBuffer::writeDataLZ4(const char *array, uint32_t length) m_nbCRCOK++; } - int compressedSize = LZ4_decompress_fast((const char*) m_lz4InBuffer, (char*) &m_rawBuffer[m_writeCount], m_frameSize); + int compressedSize = LZ4_decompress_fast((const char*) m_lz4InBuffer, (char*) &m_rawBuffer[m_writeIndex], m_frameSize); m_nbDecodes++; if (compressedSize == m_lz4InSize) @@ -199,16 +198,16 @@ void SDRdaemonBuffer::writeDataLZ4(const char *array, uint32_t length) void SDRdaemonBuffer::writeToRawBufferUncompressed(const char *array, uint32_t length) { // TODO: handle the 1 byte per I or Q sample - if (m_writeCount + length < m_rawSize) + if (m_writeIndex + length < m_rawSize) { - std::memcpy((void *) &m_rawBuffer[m_writeCount], (const void *) array, length); - m_writeCount += length; + std::memcpy((void *) &m_rawBuffer[m_writeIndex], (const void *) array, length); + m_writeIndex += length; } else { - std::memcpy((void *) &m_rawBuffer[m_writeCount], (const void *) array, m_rawSize - m_writeCount); - m_writeCount = length - (m_rawSize - m_writeCount); - std::memcpy((void *) m_rawBuffer, (const void *) &array[m_rawSize - m_writeCount], m_writeCount); + std::memcpy((void *) &m_rawBuffer[m_writeIndex], (const void *) array, m_rawSize - m_writeIndex); + m_writeIndex = length - (m_rawSize - m_writeIndex); + std::memcpy((void *) m_rawBuffer, (const void *) &array[m_rawSize - m_writeIndex], m_writeIndex); } } @@ -225,27 +224,26 @@ void SDRdaemonBuffer::writeToRawBufferLZ4(const char *array, uint32_t length) writeToRawBufferUncompressed((const char *) m_lz4OutBuffer, m_frameSize); } -uint8_t *SDRdaemonBuffer::readData(uint32_t length) +uint8_t *SDRdaemonBuffer::readDataChunk() { - if (m_readCount + length < m_rawSize) + // relies on the fact that we always have an integer number of chunks in the raw buffer + + if (m_readChunkIndex == m_rateDivider * 2) // go back to start or middle of raw buffer { - uint32_t readCount = m_readCount; - m_readCount += length; - return &m_rawBuffer[readCount]; - } - //else if (m_readCount > 0) - else - { - if (length > m_chunkSize) { - qDebug("SDRdaemonBuffer::readData: length: %d", length); + // make sure the read and write pointers are not in the same half of the raw buffer + if (m_writeIndex < m_rateDivider * m_chunkSize - 1) + { + m_readChunkIndex = m_rateDivider; // go to middle + } + else + { + m_readChunkIndex = 0; // go to start } - uint32_t retLength = std::min(length, m_chunkSize); - //uint32_t retLength = length; - std::memcpy((void *) m_chunkBuffer, (const void *) &m_rawBuffer[m_readCount], m_rawSize - m_readCount); // read last bit from raw buffer - m_readCount = retLength - (m_rawSize - m_readCount); - std::memcpy((void *) &m_chunkBuffer[m_rawSize - m_readCount], (const void *) m_rawBuffer, m_readCount); // read the rest at start of raw buffer - return m_chunkBuffer; } + + uint32_t readIndex = m_readChunkIndex; + m_readChunkIndex++; + return &m_rawBuffer[readIndex * m_chunkSize]; } void SDRdaemonBuffer::updateLZ4Sizes(uint32_t frameSize) @@ -265,35 +263,34 @@ void SDRdaemonBuffer::updateLZ4Sizes(uint32_t frameSize) m_lz4OutBuffer = new uint8_t[frameSize]; } -void SDRdaemonBuffer::updateBufferSize(uint32_t sampleRate, uint32_t frameSize) +void SDRdaemonBuffer::updateBufferSize(uint32_t sampleRate) { - uint32_t nbFrames = ((sampleRate * 2 * 2) / frameSize) + 1; // store at least 1 second of samples + assert(sampleRate % m_rateDivider == 0); // make sure we get an integer number of samples in a chunk - std::cerr << "SDRdaemonBuffer::updateBufferSize:" - << " sampleRate: " << sampleRate - << " frameSize: " << frameSize - << " nbFrames: " << nbFrames - << std::endl; + // Store 2 seconds long of samples so we have two one second long half buffers + m_chunkSize = (sampleRate * m_iqSampleSize) / m_rateDivider; + m_rawSize = m_chunkSize * m_rateDivider * 2; if (m_rawBuffer) { delete[] m_rawBuffer; } - m_rawSize = nbFrames * frameSize; m_rawBuffer = new uint8_t[m_rawSize]; - if (m_chunkBuffer) { - delete[] m_chunkBuffer; - } + m_writeIndex = 0; + m_readChunkIndex = m_rateDivider; - m_chunkSize = (sampleRate * 2 * 2) / m_rateDivider; - m_chunkBuffer = new uint8_t[m_chunkSize]; + std::cerr << "SDRdaemonBuffer::updateBufferSize:" + << " sampleRate: " << sampleRate + << " m_chunkSize: " << m_chunkSize + << " m_rawSize: " << m_rawSize + << std::endl; } void SDRdaemonBuffer::updateBlockCounts(uint32_t nbBytesReceived) { - m_nbBlocks += m_bytesInBlock + nbBytesReceived > m_blockSize ? 1 : 0; - m_bytesInBlock = m_bytesInBlock + nbBytesReceived > m_blockSize ? nbBytesReceived : m_bytesInBlock + nbBytesReceived; + m_nbBlocks += m_bytesInBlock + nbBytesReceived > m_udpPayloadSize ? 1 : 0; + m_bytesInBlock = m_bytesInBlock + nbBytesReceived > m_udpPayloadSize ? nbBytesReceived : m_bytesInBlock + nbBytesReceived; } void SDRdaemonBuffer::printMeta(MetaData *metaData) diff --git a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h index 55c6f7ca1..f2abe3346 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h +++ b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h @@ -61,24 +61,27 @@ public: }; #pragma pack(pop) - SDRdaemonBuffer(uint32_t blockSize, uint32_t rateDivider); + SDRdaemonBuffer(uint32_t rateDivider); ~SDRdaemonBuffer(); bool readMeta(char *array, uint32_t length); //!< Attempt to read meta. Returns true if meta block void writeData(char *array, uint32_t length); //!< Write data into buffer. - uint8_t *readData(uint32_t length); //!< Read data from buffer + uint8_t *readDataChunk(); //!< Read a chunk of data from buffer const MetaData& getCurrentMeta() const { return m_currentMeta; } void updateBlockCounts(uint32_t nbBytesReceived); bool isSync() const { return m_sync; } + static const int m_udpPayloadSize; + static const int m_sampleSize; + static const int m_iqSampleSize; + private: void updateLZ4Sizes(uint32_t frameSize); void writeDataLZ4(const char *array, uint32_t length); void writeToRawBufferLZ4(const char *array, uint32_t originalLength); void writeToRawBufferUncompressed(const char *array, uint32_t length); - void updateBufferSize(uint32_t sampleRate, uint32_t frameSize); + void updateBufferSize(uint32_t sampleRate); void printMeta(MetaData *metaData); - uint32_t m_blockSize; //!< UDP block (payload) size uint32_t m_rateDivider; //!< Number of times per seconds the samples are fetched bool m_sync; //!< Meta data acquired (Stream synchronized) bool m_lz4; //!< Stream is compressed with LZ4 @@ -100,11 +103,10 @@ private: uint8_t m_sampleBytes; //!< Current number of bytes per I or Q sample uint8_t m_sampleBits; //!< Current number of effective bits per sample - uint32_t m_writeCount; //!< Current write position in the raw samples buffer - uint32_t m_readCount; //!< Current read position in the raw samples buffer + uint32_t m_writeIndex; //!< Current write position in the raw samples buffer + uint32_t m_readChunkIndex; //!< Current read chunk index in the raw samples buffer uint32_t m_rawSize; //!< Size of the raw samples buffer in bytes uint8_t *m_rawBuffer; //!< Buffer for raw samples obtained from UDP (I/Q not in a formal I/Q structure) - uint8_t *m_chunkBuffer; //!< Buffer to build a chunk length of raw samples uint32_t m_chunkSize; //!< Size of a chunk of samples in bytes uint32_t m_bytesInBlock; //!< Number of bytes received in the current UDP block uint32_t m_nbBlocks; //!< Number of UDP blocks received in the current frame diff --git a/plugins/samplesource/sdrdaemon/sdrdaemonudphandler.cpp b/plugins/samplesource/sdrdaemon/sdrdaemonudphandler.cpp index 9a1c4618a..e58d509b4 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemonudphandler.cpp +++ b/plugins/samplesource/sdrdaemon/sdrdaemonudphandler.cpp @@ -23,19 +23,16 @@ #include "sdrdaemoninput.h" const int SDRdaemonUDPHandler::m_rateDivider = 1000/SDRDAEMON_THROTTLE_MS; -const int SDRdaemonUDPHandler::m_udpPayloadSize = 512; SDRdaemonUDPHandler::SDRdaemonUDPHandler(SampleFifo *sampleFifo, MessageQueue *outputMessageQueueToGUI) : //m_mutex(QMutex::Recursive), - m_sdrDaemonBuffer(m_udpPayloadSize, m_rateDivider), + m_sdrDaemonBuffer(m_rateDivider), m_dataSocket(0), m_dataAddress(QHostAddress::LocalHost), m_dataPort(9090), m_dataConnected(false), m_udpBuf(0), m_udpReadBytes(0), - m_buf(0), - m_bufsize(0), m_chunksize(0), m_sampleFifo(sampleFifo), m_samplerate(0), @@ -46,7 +43,7 @@ SDRdaemonUDPHandler::SDRdaemonUDPHandler(SampleFifo *sampleFifo, MessageQueue *o m_tickCount(0), m_samplesCount(0) { - m_udpBuf = new char[m_udpPayloadSize]; + m_udpBuf = new char[SDRdaemonBuffer::m_udpPayloadSize]; } SDRdaemonUDPHandler::~SDRdaemonUDPHandler() @@ -169,20 +166,11 @@ void SDRdaemonUDPHandler::setSamplerate(uint32_t samplerate) //QMutexLocker ml(&m_mutex); m_samplerate = samplerate; - m_chunksize = (m_samplerate / m_rateDivider)*4; // TODO: implement FF and slow motion here. 4 corresponds to live. 2 is half speed, 8 is doulbe speed - m_bufsize = m_chunksize; - - if (m_buf == 0) { - qDebug() << " - Allocate buffer"; - m_buf = (quint8*) malloc(m_bufsize); - } else { - qDebug() << " - Re-allocate buffer"; - m_buf = (quint8*) realloc((void*) m_buf, m_bufsize); - } + m_chunksize = (m_samplerate / m_rateDivider) * SDRdaemonBuffer::m_iqSampleSize; qDebug() << "SDRdaemonUDPHandler::setSamplerate:" - << " size: " << m_bufsize - << " #samples: " << (m_bufsize/4); + << " chunk size: " << m_chunksize + << " #samples per chunk: " << (m_chunksize/SDRdaemonBuffer::m_iqSampleSize); } void SDRdaemonUDPHandler::connectTimer(const QTimer& timer) @@ -194,8 +182,8 @@ void SDRdaemonUDPHandler::connectTimer(const QTimer& timer) void SDRdaemonUDPHandler::tick() { // read samples directly feeding the SampleFifo (no callback) - m_sampleFifo->write(reinterpret_cast(m_sdrDaemonBuffer.readData(m_chunksize)), m_chunksize); - m_samplesCount += m_chunksize / 4; + m_sampleFifo->write(reinterpret_cast(m_sdrDaemonBuffer.readDataChunk()), m_chunksize); + m_samplesCount += m_chunksize / SDRdaemonBuffer::m_iqSampleSize; if (m_tickCount < m_rateDivider) { diff --git a/plugins/samplesource/sdrdaemon/sdrdaemonudphandler.h b/plugins/samplesource/sdrdaemon/sdrdaemonudphandler.h index 66becc1a5..f82b2ec62 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemonudphandler.h +++ b/plugins/samplesource/sdrdaemon/sdrdaemonudphandler.h @@ -55,8 +55,6 @@ private: bool m_dataConnected; char *m_udpBuf; qint64 m_udpReadBytes; - quint8 *m_buf; - std::size_t m_bufsize; std::size_t m_chunksize; SampleFifo *m_sampleFifo; uint32_t m_samplerate; @@ -68,7 +66,6 @@ private: std::size_t m_samplesCount; static const int m_rateDivider; - static const int m_udpPayloadSize; void setSamplerate(uint32_t samplerate); void processData();