SDRAngel  4.11.5
Developer docs for <a href="https://github.com/f4exb/sdrangel">SDRangel<\a>, an Open Source Qt5 / OpenGL 3.0+ SDR and signal analyzer frontend to various hardware.
udpsinkfec.cpp
Go to the documentation of this file.
1 // Copyright (C) 2017 Edouard Griffiths, F4EXB //
3 // //
4 // This program is free software; you can redistribute it and/or modify //
5 // it under the terms of the GNU General Public License as published by //
6 // the Free Software Foundation as version 3 of the License, or //
7 // (at your option) any later version. //
8 // //
9 // This program is distributed in the hope that it will be useful, //
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of //
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
12 // GNU General Public License V3 for more details. //
13 // //
14 // You should have received a copy of the GNU General Public License //
15 // along with this program. If not, see <http://www.gnu.org/licenses/>. //
17 
18 #include "udpsinkfec.h"
19 
20 #include <QDebug>
21 
22 #include <boost/crc.hpp>
23 #include <boost/cstdint.hpp>
24 
25 #include "util/timeutil.h"
26 
27 #include "udpsinkfecworker.h"
28 
29 
31  m_sampleRate(48000),
32  m_nbSamples(0),
33  m_nbBlocksFEC(0),
34  m_txDelayRatio(0.0),
35  m_txDelay(0),
36  m_txBlockIndex(0),
37  m_txBlocksIndex(0),
38  m_frameCount(0),
39  m_sampleIndex(0),
40  m_udpWorker(0),
41  m_remoteAddress("127.0.0.1"),
42  m_remotePort(9090)
43 {
44  memset((char *) m_txBlocks, 0, 4*256*sizeof(RemoteSuperBlock));
45  memset((char *) &m_superBlock, 0, sizeof(RemoteSuperBlock));
48  m_buf = new uint8_t[m_udpSize];
49 }
50 
52 {
53  delete[] m_buf;
54  delete[] m_bufMeta;
55 }
56 
58 {
61  m_udpWorker->startStop(true);
62 }
63 
65 {
66  if (m_udpWorker)
67  {
68  m_udpWorker->startStop(false);
69  m_udpWorker->deleteLater();
70  m_udpWorker = 0;
71  }
72 }
73 
74 void UDPSinkFEC::setTxDelay(float txDelayRatio)
75 {
76  // delay is calculated from the fraction of the nominal UDP block process time
77  // frame size: 127 * (126 or 63 samples depending on I or Q sample bytes of 2 or 4 bytes respectively)
78  // divided by sample rate gives the frame process time
79  // divided by the number of actual blocks including FEC blocks gives the block (i.e. UDP block) process time
80  m_txDelayRatio = txDelayRatio;
81  int samplesPerBlock = RemoteNbBytesPerBlock / (SDR_RX_SAMP_SZ <= 16 ? 4 : 8);
82  double delay = ((127*samplesPerBlock*txDelayRatio) / m_sampleRate)/(128 + m_nbBlocksFEC);
83  m_txDelay = delay * 1e6;
84  qDebug() << "UDPSinkFEC::setTxDelay: txDelay: " << txDelayRatio << " m_txDelay: " << m_txDelay << " us";
85 }
86 
88 {
89  qDebug() << "UDPSinkFEC::setNbBlocksFEC: nbBlocksFEC: " << nbBlocksFEC;
90  m_nbBlocksFEC = nbBlocksFEC;
92 }
93 
95 {
96  qDebug() << "UDPSinkFEC::setSampleRate: sampleRate: " << sampleRate;
97  m_sampleRate = sampleRate;
99 }
100 
101 void UDPSinkFEC::setRemoteAddress(const QString& address, uint16_t port)
102 {
103  qDebug() << "UDPSinkFEC::setRemoteAddress: address: " << address << " port: " << port;
104  m_remoteAddress = address;
105  m_remotePort = port;
106 
107  if (m_udpWorker) {
109  }
110 }
111 
112 void UDPSinkFEC::write(const SampleVector::iterator& begin, uint32_t sampleChunkSize)
113 {
114  const SampleVector::iterator end = begin + sampleChunkSize;
115  SampleVector::iterator it = begin;
116 
117  while (it != end)
118  {
119  int inRemainingSamples = end - it;
120 
121  if (m_txBlockIndex == 0) // Tx block index 0 is a block with only meta data
122  {
123  RemoteMetaDataFEC metaData;
124 
125  uint64_t ts_usecs = TimeUtil::nowus();
126 
127  metaData.m_centerFrequency = 0; // frequency not set by stream
128  metaData.m_sampleRate = m_sampleRate;
129  metaData.m_sampleBytes = (SDR_RX_SAMP_SZ <= 16 ? 2 : 4);
130  metaData.m_sampleBits = SDR_RX_SAMP_SZ;
132  metaData.m_nbFECBlocks = m_nbBlocksFEC;
133  metaData.m_tv_sec = ts_usecs / 1000000UL;
134  metaData.m_tv_usec = ts_usecs % 1000000UL;
135 
136  boost::crc_32_type crc32;
137  crc32.process_bytes(&metaData, sizeof(RemoteMetaDataFEC)-4);
138 
139  metaData.m_crc32 = crc32.checksum();
140 
141  memset((char *) &m_superBlock, 0, sizeof(m_superBlock));
142 
143  m_superBlock.m_header.m_frameIndex = m_frameCount;
144  m_superBlock.m_header.m_blockIndex = m_txBlockIndex;
145  m_superBlock.m_header.m_sampleBytes = (SDR_RX_SAMP_SZ <= 16 ? 2 : 4);
146  m_superBlock.m_header.m_sampleBits = SDR_RX_SAMP_SZ;
147 
148  RemoteMetaDataFEC *destMeta = (RemoteMetaDataFEC *) &m_superBlock.m_protectedBlock;
149  *destMeta = metaData;
150 
151  if (!(metaData == m_currentMetaFEC))
152  {
153  qDebug() << "UDPSinkFEC::write: meta: "
154  << "|" << metaData.m_centerFrequency
155  << ":" << metaData.m_sampleRate
156  << ":" << (int) (metaData.m_sampleBytes & 0xF)
157  << ":" << (int) metaData.m_sampleBits
158  << "|" << (int) metaData.m_nbOriginalBlocks
159  << ":" << (int) metaData.m_nbFECBlocks
160  << "|" << metaData.m_tv_sec
161  << ":" << metaData.m_tv_usec
162  << "|";
163 
164  m_currentMetaFEC = metaData;
165  }
166 
168  m_txBlockIndex = 1; // next Tx block with data
169  }
170 
171  int samplesPerBlock = RemoteNbBytesPerBlock / (SDR_RX_SAMP_SZ <= 16 ? 4 : 8); // two I or Q samples
172 
173  if (m_sampleIndex + inRemainingSamples < samplesPerBlock) // there is still room in the current super block
174  {
175  memcpy((char *) &m_superBlock.m_protectedBlock.buf[m_sampleIndex*sizeof(Sample)],
176  (const char *) &(*it),
177  inRemainingSamples * sizeof(Sample));
178  m_sampleIndex += inRemainingSamples;
179  it = end; // all input samples are consumed
180  }
181  else // complete super block and initiate the next if not end of frame
182  {
183  memcpy((char *) &m_superBlock.m_protectedBlock.buf[m_sampleIndex*sizeof(Sample)],
184  (const char *) &(*it),
185  (samplesPerBlock - m_sampleIndex) * sizeof(Sample));
186  it += samplesPerBlock - m_sampleIndex;
187  m_sampleIndex = 0;
188 
194 
195  if (m_txBlockIndex == m_nbOriginalBlocks - 1) // frame complete
196  {
197  int nbBlocksFEC = m_nbBlocksFEC;
198  int txDelay = m_txDelay;
199 
200  if (m_udpWorker) {
202  }
203 
204  m_txBlocksIndex = (m_txBlocksIndex + 1) % 4;
205  m_txBlockIndex = 0;
206  m_frameCount++;
207  }
208  else
209  {
210  m_txBlockIndex++;
211  }
212  }
213  }
214 }
215 
uint32_t m_sampleRate
12 sample rate in Hz
uint32_t m_sampleRate
sample rate in Hz
Definition: udpsinkfec.h:81
void setTxDelay(float txDelayRatio)
Definition: udpsinkfec.cpp:74
void pushTxFrame(RemoteSuperBlock *txBlocks, uint32_t nbBlocksFEC, uint32_t txDelay, uint16_t frameIndex)
int m_txBlocksIndex
Current index of Tx blocks row.
Definition: udpsinkfec.h:97
uint16_t m_remotePort
Definition: udpsinkfec.h:103
void setRemoteAddress(const QString &address, uint16_t port)
Definition: udpsinkfec.cpp:101
int m_sampleIndex
Current sample index in protected block data.
Definition: udpsinkfec.h:99
uint32_t m_txDelay
Delay in microseconds (usleep) between each sending of an UDP datagram.
Definition: udpsinkfec.h:93
void stop()
Definition: udpsinkfec.cpp:64
RemoteProtectedBlock m_protectedBlock
void write(const SampleVector::iterator &begin, uint32_t sampleChunkSize)
Definition: udpsinkfec.cpp:112
float m_txDelayRatio
Delay in ratio of nominal frame period.
Definition: udpsinkfec.h:92
QString m_remoteAddress
Definition: udpsinkfec.h:102
unsigned int uint32_t
Definition: rtptypes_win.h:46
uint8_t * m_bufMeta
Definition: udpsinkfec.h:87
void startStop(bool start)
#define SDR_RX_SAMP_SZ
Definition: dsptypes.h:32
uint8_t m_sampleBytes
13 4 LSB: number of bytes per sample (2 or 4)
unsigned char uint8_t
Definition: rtptypes_win.h:42
RemoteMetaDataFEC m_currentMetaFEC
Meta data for current frame.
Definition: udpsinkfec.h:90
uint8_t buf[RemoteNbBytesPerBlock]
unsigned short uint16_t
Definition: rtptypes_win.h:44
RemoteSuperBlock m_txBlocks[4][256]
UDP blocks to send with original data + FEC.
Definition: udpsinkfec.h:94
uint32_t m_crc32
28 CRC32 of the above
uint8_t m_sampleBytes
number of bytes per sample (2 or 4) for this block
uint8_t m_nbFECBlocks
16 number of blocks carrying FEC
uint32_t m_tv_usec
24 microseconds of timestamp at start time of super-frame processing
uint8_t m_blockIndex
uint8_t m_sampleBits
14 number of effective bits per sample (deprecated)
void start()
Definition: udpsinkfec.cpp:57
static const uint32_t m_nbOriginalBlocks
Number of original blocks in a protected block sequence.
Definition: udpsinkfec.h:39
uint32_t m_tv_sec
20 seconds of timestamp at start time of super-frame processing
RemoteSuperBlock m_superBlock
current super block being built
Definition: udpsinkfec.h:95
static const uint32_t m_udpSize
Size of UDP block in number of bytes.
Definition: udpsinkfec.h:38
UDPSinkFECWorker * m_udpWorker
Definition: udpsinkfec.h:101
void setRemoteAddress(const QString &address, uint16_t port)
RemoteHeader m_header
static uint64_t nowus()
returns the current epoch in microseconds
Definition: timeutil.cpp:30
uint16_t m_frameIndex
uint8_t m_nbOriginalBlocks
15 number of blocks with original (protected) data
int m_txBlockIndex
Current index in blocks to transmit in the Tx row.
Definition: udpsinkfec.h:96
void setNbBlocksFEC(uint32_t nbBlocksFEC)
Definition: udpsinkfec.cpp:87
uint32_t crc32(const uint8_t *buf, int len)
Definition: crc.h:58
uint64_t m_centerFrequency
8 center frequency in kHz
uint16_t m_frameCount
transmission frame count
Definition: udpsinkfec.h:98
uint8_t * m_buf
Definition: udpsinkfec.h:88
uint8_t m_sampleBits
number of bits per sample
void setSampleRate(uint32_t sampleRate)
Definition: udpsinkfec.cpp:94
uint32_t m_nbBlocksFEC
Variable number of FEC blocks.
Definition: udpsinkfec.h:91
unsigned __int64 uint64_t
Definition: rtptypes_win.h:48