mirror of
https://github.com/f4exb/sdrangel.git
synced 2025-04-02 01:28:56 -04:00
SDRDaemon: cleanup on UDP Tx side to use sdrdaemondatablock.h definitions and Rx sample size
This commit is contained in:
parent
05072ce4b9
commit
5e588ae09e
plugins
channelrx/daemonsink
samplesink/sdrdaemonsink
sdrbase/channel
@ -52,7 +52,6 @@ DaemonSink::DaemonSink(DeviceSourceAPI *deviceAPI) :
|
||||
m_dataBlock(0),
|
||||
m_centerFrequency(0),
|
||||
m_sampleRate(48000),
|
||||
m_sampleBytes(SDR_RX_SAMP_SZ <= 16 ? 2 : 4),
|
||||
m_nbBlocksFEC(0),
|
||||
m_txDelay(35),
|
||||
m_dataAddress("127.0.0.1"),
|
||||
@ -115,7 +114,7 @@ void DaemonSink::feed(const SampleVector::const_iterator& begin, const SampleVec
|
||||
|
||||
metaData.m_centerFrequency = m_centerFrequency;
|
||||
metaData.m_sampleRate = m_sampleRate;
|
||||
metaData.m_sampleBytes = m_sampleBytes & 0xF;
|
||||
metaData.m_sampleBytes = (SDR_RX_SAMP_SZ <= 16 ? 2 : 4);
|
||||
metaData.m_sampleBits = SDR_RX_SAMP_SZ;
|
||||
metaData.m_nbOriginalBlocks = SDRDaemonNbOrginalBlocks;
|
||||
metaData.m_nbFECBlocks = m_nbBlocksFEC;
|
||||
@ -133,6 +132,8 @@ void DaemonSink::feed(const SampleVector::const_iterator& begin, const SampleVec
|
||||
superBlock.init();
|
||||
superBlock.m_header.m_frameIndex = m_frameCount;
|
||||
superBlock.m_header.m_blockIndex = m_txBlockIndex;
|
||||
superBlock.m_header.m_sampleBytes = (SDR_RX_SAMP_SZ <= 16 ? 2 : 4);
|
||||
superBlock.m_header.m_sampleBits = SDR_RX_SAMP_SZ;
|
||||
memcpy((void *) &superBlock.m_protectedBlock, (const void *) &metaData, sizeof(SDRDaemonMetaDataFEC));
|
||||
|
||||
if (!(metaData == m_currentMetaFEC))
|
||||
@ -154,7 +155,7 @@ void DaemonSink::feed(const SampleVector::const_iterator& begin, const SampleVec
|
||||
} // block zero
|
||||
|
||||
// handle different sample sizes...
|
||||
int samplesPerBlock = SDRDaemonNbBytesPerBlock / sizeof(Sample);
|
||||
int samplesPerBlock = SDRDaemonNbBytesPerBlock / (SDR_RX_SAMP_SZ <= 16 ? 4 : 8); // two I or Q samples
|
||||
if (m_sampleIndex + inRemainingSamples < samplesPerBlock) // there is still room in the current super block
|
||||
{
|
||||
memcpy((void *) &m_superBlock.m_protectedBlock.buf[m_sampleIndex*sizeof(Sample)],
|
||||
@ -173,6 +174,8 @@ void DaemonSink::feed(const SampleVector::const_iterator& begin, const SampleVec
|
||||
|
||||
m_superBlock.m_header.m_frameIndex = m_frameCount;
|
||||
m_superBlock.m_header.m_blockIndex = m_txBlockIndex;
|
||||
m_superBlock.m_header.m_sampleBytes = (SDR_RX_SAMP_SZ <= 16 ? 2 : 4);
|
||||
m_superBlock.m_header.m_sampleBits = SDR_RX_SAMP_SZ;
|
||||
m_dataBlock->m_superBlocks[m_txBlockIndex] = m_superBlock;
|
||||
|
||||
if (m_txBlockIndex == SDRDaemonNbOrginalBlocks - 1) // frame complete
|
||||
|
@ -144,7 +144,6 @@ private:
|
||||
|
||||
uint64_t m_centerFrequency;
|
||||
uint32_t m_sampleRate;
|
||||
uint8_t m_sampleBytes;
|
||||
int m_nbBlocksFEC;
|
||||
int m_txDelay;
|
||||
QString m_dataAddress;
|
||||
|
@ -132,6 +132,8 @@ void DaemonSinkThread::handleDataBlock(SDRDaemonDataBlock& dataBlock)
|
||||
|
||||
txBlockx[i].m_header.m_frameIndex = frameIndex;
|
||||
txBlockx[i].m_header.m_blockIndex = i;
|
||||
txBlockx[i].m_header.m_sampleBytes = (SDR_RX_SAMP_SZ <= 16 ? 2 : 4);
|
||||
txBlockx[i].m_header.m_sampleBits = SDR_RX_SAMP_SZ;
|
||||
descriptorBlocks[i].Block = (void *) &(txBlockx[i].m_protectedBlock);
|
||||
descriptorBlocks[i].Index = txBlockx[i].m_header.m_blockIndex;
|
||||
}
|
||||
|
@ -69,6 +69,7 @@ private:
|
||||
QMutex m_startWaitMutex;
|
||||
QWaitCondition m_startWaiter;
|
||||
bool m_running;
|
||||
uint8_t m_sampleBytes;
|
||||
|
||||
CM256 m_cm256;
|
||||
CM256 *m_cm256p;
|
||||
|
@ -38,6 +38,7 @@
|
||||
|
||||
#include "device/devicesinkapi.h"
|
||||
#include "device/deviceuiset.h"
|
||||
#include "channel/sdrdaemondatablock.h"
|
||||
#include "udpsinkfec.h"
|
||||
#include "sdrdaemonsinkgui.h"
|
||||
|
||||
@ -215,7 +216,7 @@ void SDRdaemonSinkGui::updateSampleRate()
|
||||
|
||||
void SDRdaemonSinkGui::updateTxDelayTooltip()
|
||||
{
|
||||
int samplesPerBlock = UDPSinkFEC::bytesPerBlock / (SDR_TX_SAMP_SZ <= 16 ? 4 : 8);
|
||||
int samplesPerBlock = SDRDaemonNbBytesPerBlock / (SDR_RX_SAMP_SZ <= 16 ? 4 : 8);
|
||||
double delay = ((127*samplesPerBlock*m_settings.m_txDelay) / m_settings.m_sampleRate)/(128 + m_settings.m_nbFECBlocks);
|
||||
ui->txDelayText->setToolTip(tr("%1 us").arg(QString::number(delay*1e6, 'f', 0)));
|
||||
}
|
||||
|
@ -29,8 +29,6 @@ MESSAGE_CLASS_DEFINITION(UDPSinkFECWorker::MsgConfigureRemoteAddress, Message)
|
||||
|
||||
UDPSinkFEC::UDPSinkFEC() :
|
||||
m_sampleRate(48000),
|
||||
m_sampleBytes(SDR_TX_SAMP_SZ <= 16 ? 2 : 4),
|
||||
m_sampleBits(SDR_TX_SAMP_SZ),
|
||||
m_nbSamples(0),
|
||||
m_nbBlocksFEC(0),
|
||||
m_txDelayRatio(0.0),
|
||||
@ -40,8 +38,8 @@ UDPSinkFEC::UDPSinkFEC() :
|
||||
m_frameCount(0),
|
||||
m_sampleIndex(0)
|
||||
{
|
||||
memset((char *) m_txBlocks, 0, 4*256*sizeof(SuperBlock));
|
||||
memset((char *) &m_superBlock, 0, sizeof(SuperBlock));
|
||||
memset((char *) m_txBlocks, 0, 4*256*sizeof(SDRDaemonSuperBlock));
|
||||
memset((char *) &m_superBlock, 0, sizeof(SDRDaemonSuperBlock));
|
||||
m_currentMetaFEC.init();
|
||||
m_bufMeta = new uint8_t[m_udpSize];
|
||||
m_buf = new uint8_t[m_udpSize];
|
||||
@ -74,7 +72,7 @@ void UDPSinkFEC::setTxDelay(float txDelayRatio)
|
||||
// divided by sample rate gives the frame process time
|
||||
// divided by the number of actual blocks including FEC blocks gives the block (i.e. UDP block) process time
|
||||
m_txDelayRatio = txDelayRatio;
|
||||
int samplesPerBlock = bytesPerBlock / (m_sampleBytes*2);
|
||||
int samplesPerBlock = SDRDaemonNbBytesPerBlock / (SDR_RX_SAMP_SZ <= 16 ? 4 : 8);
|
||||
double delay = ((127*samplesPerBlock*txDelayRatio) / m_sampleRate)/(128 + m_nbBlocksFEC);
|
||||
m_txDelay = delay * 1e6;
|
||||
qDebug() << "UDPSinkFEC::setTxDelay: txDelay: " << txDelayRatio << " m_txDelay: " << m_txDelay << " us";
|
||||
@ -113,14 +111,14 @@ void UDPSinkFEC::write(const SampleVector::iterator& begin, uint32_t sampleChunk
|
||||
if (m_txBlockIndex == 0) // Tx block index 0 is a block with only meta data
|
||||
{
|
||||
struct timeval tv;
|
||||
MetaDataFEC metaData;
|
||||
SDRDaemonMetaDataFEC metaData;
|
||||
|
||||
gettimeofday(&tv, 0);
|
||||
|
||||
metaData.m_centerFrequency = 0; // frequency not set by stream
|
||||
metaData.m_sampleRate = m_sampleRate;
|
||||
metaData.m_sampleBytes = m_sampleBytes & 0xF;
|
||||
metaData.m_sampleBits = m_sampleBits;
|
||||
metaData.m_sampleBytes = (SDR_RX_SAMP_SZ <= 16 ? 2 : 4);
|
||||
metaData.m_sampleBits = SDR_RX_SAMP_SZ;
|
||||
metaData.m_nbOriginalBlocks = m_nbOriginalBlocks;
|
||||
metaData.m_nbFECBlocks = m_nbBlocksFEC;
|
||||
metaData.m_tv_sec = tv.tv_sec;
|
||||
@ -133,9 +131,11 @@ void UDPSinkFEC::write(const SampleVector::iterator& begin, uint32_t sampleChunk
|
||||
|
||||
memset((char *) &m_superBlock, 0, sizeof(m_superBlock));
|
||||
|
||||
m_superBlock.header.frameIndex = m_frameCount;
|
||||
m_superBlock.header.blockIndex = m_txBlockIndex;
|
||||
memcpy((char *) &m_superBlock.protectedBlock, (const char *) &metaData, sizeof(MetaDataFEC));
|
||||
m_superBlock.m_header.m_frameIndex = m_frameCount;
|
||||
m_superBlock.m_header.m_blockIndex = m_txBlockIndex;
|
||||
m_superBlock.m_header.m_sampleBytes = (SDR_RX_SAMP_SZ <= 16 ? 2 : 4);
|
||||
m_superBlock.m_header.m_sampleBits = SDR_RX_SAMP_SZ;
|
||||
memcpy((char *) &m_superBlock.m_protectedBlock, (const char *) &metaData, sizeof(SDRDaemonMetaDataFEC));
|
||||
|
||||
if (!(metaData == m_currentMetaFEC))
|
||||
{
|
||||
@ -157,74 +157,28 @@ void UDPSinkFEC::write(const SampleVector::iterator& begin, uint32_t sampleChunk
|
||||
m_txBlockIndex = 1; // next Tx block with data
|
||||
}
|
||||
|
||||
int samplesPerBlock = bytesPerBlock / (m_sampleBytes*2);
|
||||
int samplesPerBlock = SDRDaemonNbBytesPerBlock / (SDR_RX_SAMP_SZ <= 16 ? 4 : 8); // two I or Q samples
|
||||
|
||||
if (m_sampleIndex + inRemainingSamples < samplesPerBlock) // there is still room in the current super block
|
||||
{
|
||||
if (sizeof(Sample) == m_sampleBytes*2) // can do direct copy if sample sizes are equal
|
||||
{
|
||||
memcpy((char *) &m_superBlock.protectedBlock.m_buf[m_sampleIndex*m_sampleBytes*2],
|
||||
(const char *) &(*it),
|
||||
inRemainingSamples * sizeof(Sample));
|
||||
}
|
||||
else if ((sizeof(Sample) == 8) && (m_sampleBytes == 2)) // modulators produce 16 bit samples
|
||||
{
|
||||
for (int is = 0; is < inRemainingSamples; is++)
|
||||
{
|
||||
int16_t *rp = (int16_t*) &(m_superBlock.protectedBlock.m_buf[(m_sampleIndex+is)*m_sampleBytes*2]);
|
||||
int16_t *ip = (int16_t*) &(m_superBlock.protectedBlock.m_buf[(m_sampleIndex+is)*m_sampleBytes*2+2]);
|
||||
*rp = (it+is)->m_real & 0xFFFF;
|
||||
*ip = (it+is)->m_imag & 0xFFFF;
|
||||
}
|
||||
}
|
||||
else if ((sizeof(Sample) == 4) && (m_sampleBytes == 4)) // use 16 bit samples for Tx
|
||||
{
|
||||
for (int is = 0; is < inRemainingSamples; is++)
|
||||
{
|
||||
int32_t *rp = (int32_t*) &(m_superBlock.protectedBlock.m_buf[(m_sampleIndex+is)*m_sampleBytes*2]);
|
||||
int32_t *ip = (int32_t*) &(m_superBlock.protectedBlock.m_buf[(m_sampleIndex+is)*m_sampleBytes*2+4]);
|
||||
*rp = (it+is)->m_real;
|
||||
*ip = (it+is)->m_imag;
|
||||
}
|
||||
}
|
||||
|
||||
memcpy((char *) &m_superBlock.m_protectedBlock.buf[m_sampleIndex*sizeof(Sample)],
|
||||
(const char *) &(*it),
|
||||
inRemainingSamples * sizeof(Sample));
|
||||
m_sampleIndex += inRemainingSamples;
|
||||
it = end; // all input samples are consumed
|
||||
}
|
||||
else // complete super block and initiate the next if not end of frame
|
||||
{
|
||||
if (sizeof(Sample) == m_sampleBytes*2) // can do direct copy if sample sizes are equal
|
||||
{
|
||||
memcpy((char *) &m_superBlock.protectedBlock.m_buf[m_sampleIndex*m_sampleBytes*2],
|
||||
(const char *) &(*it),
|
||||
(samplesPerBlock - m_sampleIndex) * sizeof(Sample));
|
||||
}
|
||||
else if ((sizeof(Sample) == 8) && (m_sampleBytes == 2)) // modulators produce 16 bit samples
|
||||
{
|
||||
for (int is = 0; is < samplesPerBlock - m_sampleIndex; is++)
|
||||
{
|
||||
int16_t *rp = (int16_t*) &(m_superBlock.protectedBlock.m_buf[(m_sampleIndex+is)*m_sampleBytes*2]);
|
||||
int16_t *ip = (int16_t*) &(m_superBlock.protectedBlock.m_buf[(m_sampleIndex+is)*m_sampleBytes*2+2]);
|
||||
*rp = (it+is)->m_real & 0xFFFF;
|
||||
*ip = (it+is)->m_imag & 0xFFFF;
|
||||
}
|
||||
}
|
||||
else if ((sizeof(Sample) == 4) && (m_sampleBytes == 4)) // use 16 bit samples for Tx
|
||||
{
|
||||
for (int is = 0; is < samplesPerBlock - m_sampleIndex; is++)
|
||||
{
|
||||
int32_t *rp = (int32_t*) &(m_superBlock.protectedBlock.m_buf[(m_sampleIndex+is)*m_sampleBytes*2]);
|
||||
int32_t *ip = (int32_t*) &(m_superBlock.protectedBlock.m_buf[(m_sampleIndex+is)*m_sampleBytes*2+4]);
|
||||
*rp = (it+is)->m_real;
|
||||
*ip = (it+is)->m_imag;
|
||||
}
|
||||
}
|
||||
|
||||
memcpy((char *) &m_superBlock.m_protectedBlock.buf[m_sampleIndex*sizeof(Sample)],
|
||||
(const char *) &(*it),
|
||||
(samplesPerBlock - m_sampleIndex) * sizeof(Sample));
|
||||
it += samplesPerBlock - m_sampleIndex;
|
||||
m_sampleIndex = 0;
|
||||
|
||||
m_superBlock.header.frameIndex = m_frameCount;
|
||||
m_superBlock.header.blockIndex = m_txBlockIndex;
|
||||
m_superBlock.m_header.m_frameIndex = m_frameCount;
|
||||
m_superBlock.m_header.m_blockIndex = m_txBlockIndex;
|
||||
m_superBlock.m_header.m_sampleBytes = (SDR_RX_SAMP_SZ <= 16 ? 2 : 4);
|
||||
m_superBlock.m_header.m_sampleBits = SDR_RX_SAMP_SZ;
|
||||
m_txBlocks[m_txBlocksIndex][m_txBlockIndex] = m_superBlock;
|
||||
|
||||
if (m_txBlockIndex == m_nbOriginalBlocks - 1) // frame complete
|
||||
@ -263,7 +217,7 @@ UDPSinkFECWorker::~UDPSinkFECWorker()
|
||||
m_inputMessageQueue.clear();
|
||||
}
|
||||
|
||||
void UDPSinkFECWorker::pushTxFrame(UDPSinkFEC::SuperBlock *txBlocks,
|
||||
void UDPSinkFECWorker::pushTxFrame(SDRDaemonSuperBlock *txBlocks,
|
||||
uint32_t nbBlocksFEC,
|
||||
uint32_t txDelay,
|
||||
uint16_t frameIndex)
|
||||
@ -320,11 +274,11 @@ void UDPSinkFECWorker::handleInputMessages()
|
||||
}
|
||||
}
|
||||
|
||||
void UDPSinkFECWorker::encodeAndTransmit(UDPSinkFEC::SuperBlock *txBlockx, uint16_t frameIndex, uint32_t nbBlocksFEC, uint32_t txDelay)
|
||||
void UDPSinkFECWorker::encodeAndTransmit(SDRDaemonSuperBlock *txBlockx, uint16_t frameIndex, uint32_t nbBlocksFEC, uint32_t txDelay)
|
||||
{
|
||||
CM256::cm256_encoder_params cm256Params; //!< Main interface with CM256 encoder
|
||||
CM256::cm256_block descriptorBlocks[256]; //!< Pointers to data for CM256 encoder
|
||||
UDPSinkFEC::ProtectedBlock fecBlocks[256]; //!< FEC data
|
||||
SDRDaemonProtectedBlock fecBlocks[256]; //!< FEC data
|
||||
|
||||
if ((nbBlocksFEC == 0) || !m_cm256Valid)
|
||||
{
|
||||
@ -339,7 +293,7 @@ void UDPSinkFECWorker::encodeAndTransmit(UDPSinkFEC::SuperBlock *txBlockx, uint1
|
||||
}
|
||||
else
|
||||
{
|
||||
cm256Params.BlockBytes = sizeof(UDPSinkFEC::ProtectedBlock);
|
||||
cm256Params.BlockBytes = sizeof(SDRDaemonProtectedBlock);
|
||||
cm256Params.OriginalCount = UDPSinkFEC::m_nbOriginalBlocks;
|
||||
cm256Params.RecoveryCount = nbBlocksFEC;
|
||||
|
||||
@ -348,13 +302,15 @@ void UDPSinkFECWorker::encodeAndTransmit(UDPSinkFEC::SuperBlock *txBlockx, uint1
|
||||
for (int i = 0; i < cm256Params.OriginalCount + cm256Params.RecoveryCount; ++i)
|
||||
{
|
||||
if (i >= cm256Params.OriginalCount) {
|
||||
memset((char *) &txBlockx[i].protectedBlock, 0, sizeof(UDPSinkFEC::ProtectedBlock));
|
||||
memset((char *) &txBlockx[i].m_protectedBlock, 0, sizeof(SDRDaemonProtectedBlock));
|
||||
}
|
||||
|
||||
txBlockx[i].header.frameIndex = frameIndex;
|
||||
txBlockx[i].header.blockIndex = i;
|
||||
descriptorBlocks[i].Block = (void *) &(txBlockx[i].protectedBlock);
|
||||
descriptorBlocks[i].Index = txBlockx[i].header.blockIndex;
|
||||
txBlockx[i].m_header.m_frameIndex = frameIndex;
|
||||
txBlockx[i].m_header.m_blockIndex = i;
|
||||
txBlockx[i].m_header.m_sampleBytes = (SDR_RX_SAMP_SZ <= 16 ? 2 : 4);
|
||||
txBlockx[i].m_header.m_sampleBits = SDR_RX_SAMP_SZ;
|
||||
descriptorBlocks[i].Block = (void *) &(txBlockx[i].m_protectedBlock);
|
||||
descriptorBlocks[i].Index = txBlockx[i].m_header.m_blockIndex;
|
||||
}
|
||||
|
||||
// Encode FEC blocks
|
||||
@ -367,7 +323,7 @@ void UDPSinkFECWorker::encodeAndTransmit(UDPSinkFEC::SuperBlock *txBlockx, uint1
|
||||
// Merge FEC with data to transmit
|
||||
for (int i = 0; i < cm256Params.RecoveryCount; i++)
|
||||
{
|
||||
txBlockx[i + cm256Params.OriginalCount].protectedBlock = fecBlocks[i];
|
||||
txBlockx[i + cm256Params.OriginalCount].m_protectedBlock = fecBlocks[i];
|
||||
}
|
||||
|
||||
// Transmit all blocks
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include "util/CRC64.h"
|
||||
#include "util/messagequeue.h"
|
||||
#include "util/message.h"
|
||||
#include "channel/sdrdaemondatablock.h"
|
||||
|
||||
#include "UDPSocket.h"
|
||||
|
||||
@ -42,52 +43,52 @@ class UDPSinkFEC : public QObject
|
||||
public:
|
||||
static const uint32_t m_udpSize = 512; //!< Size of UDP block in number of bytes
|
||||
static const uint32_t m_nbOriginalBlocks = 128; //!< Number of original blocks in a protected block sequence
|
||||
#pragma pack(push, 1)
|
||||
struct MetaDataFEC
|
||||
{
|
||||
uint32_t m_centerFrequency; //!< 4 center frequency in kHz
|
||||
uint32_t m_sampleRate; //!< 8 sample rate in Hz
|
||||
uint8_t m_sampleBytes; //!< 9 MSB(4): indicators, LSB(4) number of bytes per sample
|
||||
uint8_t m_sampleBits; //!< 10 number of effective bits per sample
|
||||
uint8_t m_nbOriginalBlocks; //!< 11 number of blocks with original (protected) data
|
||||
uint8_t m_nbFECBlocks; //!< 12 number of blocks carrying FEC
|
||||
uint32_t m_tv_sec; //!< 16 seconds of timestamp at start time of super-frame processing
|
||||
uint32_t m_tv_usec; //!< 20 microseconds of timestamp at start time of super-frame processing
|
||||
uint32_t m_crc32; //!< 24 CRC32 of the above
|
||||
|
||||
bool operator==(const MetaDataFEC& rhs)
|
||||
{
|
||||
return (memcmp((const char *) this, (const char *) &rhs, 12) == 0); // Only the 12 first bytes are relevant
|
||||
}
|
||||
|
||||
void init()
|
||||
{
|
||||
memset((char *) this, 0, sizeof(MetaDataFEC));
|
||||
m_nbFECBlocks = -1;
|
||||
}
|
||||
};
|
||||
|
||||
struct Header
|
||||
{
|
||||
uint16_t frameIndex;
|
||||
uint8_t blockIndex;
|
||||
uint8_t filler;
|
||||
uint32_t filler2;
|
||||
};
|
||||
|
||||
static const int bytesPerBlock = m_udpSize - sizeof(Header);
|
||||
|
||||
struct ProtectedBlock
|
||||
{
|
||||
uint8_t m_buf[bytesPerBlock];
|
||||
};
|
||||
|
||||
struct SuperBlock
|
||||
{
|
||||
Header header;
|
||||
ProtectedBlock protectedBlock;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
//#pragma pack(push, 1)
|
||||
// struct MetaDataFEC
|
||||
// {
|
||||
// uint32_t m_centerFrequency; //!< 4 center frequency in kHz
|
||||
// uint32_t m_sampleRate; //!< 8 sample rate in Hz
|
||||
// uint8_t m_sampleBytes; //!< 9 MSB(4): indicators, LSB(4) number of bytes per sample
|
||||
// uint8_t m_sampleBits; //!< 10 number of effective bits per sample
|
||||
// uint8_t m_nbOriginalBlocks; //!< 11 number of blocks with original (protected) data
|
||||
// uint8_t m_nbFECBlocks; //!< 12 number of blocks carrying FEC
|
||||
// uint32_t m_tv_sec; //!< 16 seconds of timestamp at start time of super-frame processing
|
||||
// uint32_t m_tv_usec; //!< 20 microseconds of timestamp at start time of super-frame processing
|
||||
// uint32_t m_crc32; //!< 24 CRC32 of the above
|
||||
//
|
||||
// bool operator==(const MetaDataFEC& rhs)
|
||||
// {
|
||||
// return (memcmp((const char *) this, (const char *) &rhs, 12) == 0); // Only the 12 first bytes are relevant
|
||||
// }
|
||||
//
|
||||
// void init()
|
||||
// {
|
||||
// memset((char *) this, 0, sizeof(MetaDataFEC));
|
||||
// m_nbFECBlocks = -1;
|
||||
// }
|
||||
// };
|
||||
//
|
||||
// struct Header
|
||||
// {
|
||||
// uint16_t frameIndex;
|
||||
// uint8_t blockIndex;
|
||||
// uint8_t filler;
|
||||
// uint32_t filler2;
|
||||
// };
|
||||
//
|
||||
// static const int bytesPerBlock = m_udpSize - sizeof(Header);
|
||||
//
|
||||
// struct ProtectedBlock
|
||||
// {
|
||||
// uint8_t m_buf[bytesPerBlock];
|
||||
// };
|
||||
//
|
||||
// struct SuperBlock
|
||||
// {
|
||||
// Header header;
|
||||
// ProtectedBlock protectedBlock;
|
||||
// };
|
||||
//#pragma pack(pop)
|
||||
|
||||
/**
|
||||
* Construct UDP sink
|
||||
@ -127,8 +128,6 @@ private:
|
||||
std::string m_error;
|
||||
|
||||
uint32_t m_sampleRate; //!< sample rate in Hz
|
||||
uint8_t m_sampleBytes; //!< number of bytes per sample
|
||||
uint8_t m_sampleBits; //!< number of effective bits per sample
|
||||
uint32_t m_nbSamples; //!< total number of samples sent int the last frame
|
||||
|
||||
QHostAddress m_ownAddress;
|
||||
@ -137,16 +136,16 @@ private:
|
||||
uint8_t* m_bufMeta;
|
||||
uint8_t* m_buf;
|
||||
|
||||
MetaDataFEC m_currentMetaFEC; //!< Meta data for current frame
|
||||
uint32_t m_nbBlocksFEC; //!< Variable number of FEC blocks
|
||||
float m_txDelayRatio; //!< Delay in ratio of nominal frame period
|
||||
uint32_t m_txDelay; //!< Delay in microseconds (usleep) between each sending of an UDP datagram
|
||||
SuperBlock m_txBlocks[4][256]; //!< UDP blocks to send with original data + FEC
|
||||
SuperBlock m_superBlock; //!< current super block being built
|
||||
int m_txBlockIndex; //!< Current index in blocks to transmit in the Tx row
|
||||
int m_txBlocksIndex; //!< Current index of Tx blocks row
|
||||
uint16_t m_frameCount; //!< transmission frame count
|
||||
int m_sampleIndex; //!< Current sample index in protected block data
|
||||
SDRDaemonMetaDataFEC m_currentMetaFEC; //!< Meta data for current frame
|
||||
uint32_t m_nbBlocksFEC; //!< Variable number of FEC blocks
|
||||
float m_txDelayRatio; //!< Delay in ratio of nominal frame period
|
||||
uint32_t m_txDelay; //!< Delay in microseconds (usleep) between each sending of an UDP datagram
|
||||
SDRDaemonSuperBlock m_txBlocks[4][256]; //!< UDP blocks to send with original data + FEC
|
||||
SDRDaemonSuperBlock m_superBlock; //!< current super block being built
|
||||
int m_txBlockIndex; //!< Current index in blocks to transmit in the Tx row
|
||||
int m_txBlocksIndex; //!< Current index of Tx blocks row
|
||||
uint16_t m_frameCount; //!< transmission frame count
|
||||
int m_sampleIndex; //!< Current sample index in protected block data
|
||||
|
||||
QThread *m_udpThread;
|
||||
UDPSinkFECWorker *m_udpWorker;
|
||||
@ -161,13 +160,13 @@ public:
|
||||
{
|
||||
MESSAGE_CLASS_DECLARATION
|
||||
public:
|
||||
UDPSinkFEC::SuperBlock *getTxBlocks() const { return m_txBlockx; }
|
||||
SDRDaemonSuperBlock *getTxBlocks() const { return m_txBlockx; }
|
||||
uint32_t getNbBlocsFEC() const { return m_nbBlocksFEC; }
|
||||
uint32_t getTxDelay() const { return m_txDelay; }
|
||||
uint16_t getFrameIndex() const { return m_frameIndex; }
|
||||
|
||||
static MsgUDPFECEncodeAndSend* create(
|
||||
UDPSinkFEC::SuperBlock *txBlocks,
|
||||
SDRDaemonSuperBlock *txBlocks,
|
||||
uint32_t nbBlocksFEC,
|
||||
uint32_t txDelay,
|
||||
uint16_t frameIndex)
|
||||
@ -176,13 +175,13 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
UDPSinkFEC::SuperBlock *m_txBlockx;
|
||||
SDRDaemonSuperBlock *m_txBlockx;
|
||||
uint32_t m_nbBlocksFEC;
|
||||
uint32_t m_txDelay;
|
||||
uint16_t m_frameIndex;
|
||||
|
||||
MsgUDPFECEncodeAndSend(
|
||||
UDPSinkFEC::SuperBlock *txBlocks,
|
||||
SDRDaemonSuperBlock *txBlocks,
|
||||
uint32_t nbBlocksFEC,
|
||||
uint32_t txDelay,
|
||||
uint16_t frameIndex) :
|
||||
@ -218,7 +217,7 @@ public:
|
||||
UDPSinkFECWorker();
|
||||
~UDPSinkFECWorker();
|
||||
|
||||
void pushTxFrame(UDPSinkFEC::SuperBlock *txBlocks,
|
||||
void pushTxFrame(SDRDaemonSuperBlock *txBlocks,
|
||||
uint32_t nbBlocksFEC,
|
||||
uint32_t txDelay,
|
||||
uint16_t frameIndex);
|
||||
@ -237,7 +236,7 @@ private slots:
|
||||
void handleInputMessages();
|
||||
|
||||
private:
|
||||
void encodeAndTransmit(UDPSinkFEC::SuperBlock *txBlockx, uint16_t frameIndex, uint32_t nbBlocksFEC, uint32_t txDelay);
|
||||
void encodeAndTransmit(SDRDaemonSuperBlock *txBlockx, uint16_t frameIndex, uint32_t nbBlocksFEC, uint32_t txDelay);
|
||||
|
||||
volatile bool m_running;
|
||||
CM256 m_cm256; //!< CM256 library object
|
||||
|
@ -38,7 +38,7 @@ struct SDRDaemonMetaDataFEC
|
||||
{
|
||||
uint32_t m_centerFrequency; //!< 4 center frequency in kHz
|
||||
uint32_t m_sampleRate; //!< 8 sample rate in Hz
|
||||
uint8_t m_sampleBytes; //!< 9 4 LSB: number of bytes per sample (2 or 3)
|
||||
uint8_t m_sampleBytes; //!< 9 4 LSB: number of bytes per sample (2 or 4)
|
||||
uint8_t m_sampleBits; //!< 10 number of effective bits per sample (deprecated)
|
||||
uint8_t m_nbOriginalBlocks; //!< 11 number of blocks with original (protected) data
|
||||
uint8_t m_nbFECBlocks; //!< 12 number of blocks carrying FEC
|
||||
@ -69,13 +69,17 @@ struct SDRDaemonHeader
|
||||
{
|
||||
uint16_t m_frameIndex;
|
||||
uint8_t m_blockIndex;
|
||||
uint8_t m_sampleBytes; //!< number of bytes per sample (2 or 4) for this block
|
||||
uint8_t m_sampleBits; //!< number of bits per sample
|
||||
uint8_t m_filler;
|
||||
uint32_t m_filler2;
|
||||
uint16_t m_filler2;
|
||||
|
||||
void init()
|
||||
{
|
||||
m_frameIndex = 0;
|
||||
m_blockIndex = 0;
|
||||
m_sampleBytes = 2;
|
||||
m_sampleBits = 16;
|
||||
m_filler = 0;
|
||||
m_filler2 = 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user