| 
									
										
										
										
											2021-03-18 17:17:58 +00:00
										 |  |  | ///////////////////////////////////////////////////////////////////////////////////
 | 
					
						
							|  |  |  | // Copyright (C) 2017 Edouard Griffiths, F4EXB                                   //
 | 
					
						
							|  |  |  | // Copyright (C) 2021 Jon Beniston, M7RCE                                        //
 | 
					
						
							|  |  |  | //                                                                               //
 | 
					
						
							|  |  |  | // 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 as version 3 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 V3 for more details.                               //
 | 
					
						
							|  |  |  | //                                                                               //
 | 
					
						
							|  |  |  | // You should have received a copy of the GNU General Public License             //
 | 
					
						
							|  |  |  | // along with this program. If not, see <http://www.gnu.org/licenses/>.          //
 | 
					
						
							|  |  |  | ///////////////////////////////////////////////////////////////////////////////////
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define BOOST_CHRONO_HEADER_ONLY
 | 
					
						
							|  |  |  | #include <boost/chrono/chrono.hpp>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | //#include <time.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <QDebug>
 | 
					
						
							|  |  |  | #include <QNetworkAccessManager>
 | 
					
						
							|  |  |  | #include <QNetworkReply>
 | 
					
						
							|  |  |  | #include <QBuffer>
 | 
					
						
							|  |  |  | #include <QUdpSocket>
 | 
					
						
							|  |  |  | #include <QHostAddress>
 | 
					
						
							|  |  |  | #include <QNetworkDatagram>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | extern "C" | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | #include <libavcodec/avcodec.h>
 | 
					
						
							|  |  |  | #include <libavformat/avformat.h>
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "dsp/dspcommands.h"
 | 
					
						
							|  |  |  | #include "device/deviceapi.h"
 | 
					
						
							|  |  |  | #include "util/db.h"
 | 
					
						
							|  |  |  | #include "util/messagequeue.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "datvmodreport.h"
 | 
					
						
							|  |  |  | #include "datvmodsource.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-28 16:10:04 +01:00
										 |  |  | #ifdef _WIN32
 | 
					
						
							|  |  |  | #include <winsock.h>
 | 
					
						
							|  |  |  | #pragma comment(lib, "Ws2_32.lib")
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-18 17:17:58 +00:00
										 |  |  | const int DATVModSource::m_levelNbSamples = 10000; // every 10ms
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Get transport stream bitrate from file
 | 
					
						
							|  |  |  | int DATVModSource::getTSBitrate(const QString& filename) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     AVFormatContext *fmtCtx = nullptr; | 
					
						
							|  |  |  |     QByteArray ba = filename.toLocal8Bit(); | 
					
						
							|  |  |  |     const char *filenameChars = ba.data(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (avformat_open_input(&fmtCtx, filenameChars, nullptr, nullptr) < 0) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         qCritical() << "DATVModSource: Could not open source file " << filename; | 
					
						
							|  |  |  |         return -1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (avformat_find_stream_info(fmtCtx, nullptr) < 0) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         qCritical() << "DATVModSource: Could not find stream information for " << filename; | 
					
						
							|  |  |  |         avformat_close_input(&fmtCtx); | 
					
						
							|  |  |  |         return -1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     int bitrate = fmtCtx->bit_rate; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     avformat_close_input(&fmtCtx); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return bitrate; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Get data bitrate (i.e. excluding FEC overhead)
 | 
					
						
							| 
									
										
										
										
											2021-10-20 23:01:44 +02:00
										 |  |  | int DATVModSource::getDVBSDataBitrate(const DATVModSettings& settings) const | 
					
						
							| 
									
										
										
										
											2021-03-18 17:17:58 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-03-31 16:41:42 +01:00
										 |  |  |     float fecFactor; | 
					
						
							|  |  |  |     float plFactor; | 
					
						
							| 
									
										
										
										
											2021-03-18 17:17:58 +00:00
										 |  |  |     float bitsPerSymbol; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     switch (settings.m_modulation) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |     case DATVModSettings::BPSK: | 
					
						
							|  |  |  |         bitsPerSymbol = 1.0f; | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case DATVModSettings::QPSK: | 
					
						
							|  |  |  |         bitsPerSymbol = 2.0f; | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case DATVModSettings::PSK8: | 
					
						
							|  |  |  |         bitsPerSymbol = 3.0f; | 
					
						
							|  |  |  |         break; | 
					
						
							| 
									
										
										
										
											2021-03-18 20:33:52 +00:00
										 |  |  |     case DATVModSettings::APSK16: | 
					
						
							|  |  |  |         bitsPerSymbol = 4.0f; | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case DATVModSettings::APSK32: | 
					
						
							|  |  |  |         bitsPerSymbol = 5.0f; | 
					
						
							|  |  |  |         break; | 
					
						
							| 
									
										
										
										
											2021-03-18 17:17:58 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-31 16:41:42 +01:00
										 |  |  |     if (settings.m_standard == DATVModSettings::DVB_S) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         float rsFactor; | 
					
						
							|  |  |  |         float convFactor; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         rsFactor = DVBS::tsPacketLen/(float)DVBS::rsPacketLen; | 
					
						
							|  |  |  |         switch (settings.m_fec) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |         case DATVModSettings::FEC12: | 
					
						
							|  |  |  |             convFactor = 1.0f/2.0f; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         case DATVModSettings::FEC23: | 
					
						
							|  |  |  |             convFactor = 2.0f/3.0f; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         case DATVModSettings::FEC34: | 
					
						
							|  |  |  |             convFactor = 3.0f/4.0f; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         case DATVModSettings::FEC56: | 
					
						
							|  |  |  |             convFactor = 5.0f/6.0f; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         case DATVModSettings::FEC78: | 
					
						
							|  |  |  |             convFactor = 7.0f/8.0f; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         case DATVModSettings::FEC45: | 
					
						
							|  |  |  |             convFactor = 4.0f/5.0f; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         case DATVModSettings::FEC89: | 
					
						
							|  |  |  |             convFactor = 8.0f/9.0f; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         case DATVModSettings::FEC910: | 
					
						
							|  |  |  |             convFactor = 9.0f/10.0f; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         case DATVModSettings::FEC14: | 
					
						
							|  |  |  |             convFactor = 1.0f/4.0f; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         case DATVModSettings::FEC13: | 
					
						
							|  |  |  |             convFactor = 1.0f/3.0f; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         case DATVModSettings::FEC25: | 
					
						
							|  |  |  |             convFactor = 2.0f/5.0f; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         case DATVModSettings::FEC35: | 
					
						
							|  |  |  |             convFactor = 3.0f/5.0f; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         fecFactor = rsFactor * convFactor; | 
					
						
							|  |  |  |         plFactor = 1.0f; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         // For normal frames
 | 
					
						
							|  |  |  |         int codedBlockSize = 64800; | 
					
						
							|  |  |  |         int uncodedBlockSize; | 
					
						
							|  |  |  |         int bbHeaderBits = 80; | 
					
						
							|  |  |  |         // See table 5a in DVBS2 spec
 | 
					
						
							|  |  |  |         switch (settings.m_fec) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |         case DATVModSettings::FEC12: | 
					
						
							|  |  |  |             uncodedBlockSize = 32208; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         case DATVModSettings::FEC23: | 
					
						
							|  |  |  |             uncodedBlockSize = 43040; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         case DATVModSettings::FEC34: | 
					
						
							|  |  |  |             uncodedBlockSize = 48408; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         case DATVModSettings::FEC56: | 
					
						
							|  |  |  |             uncodedBlockSize = 53840; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         case DATVModSettings::FEC45: | 
					
						
							|  |  |  |             uncodedBlockSize = 51648; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         case DATVModSettings::FEC89: | 
					
						
							|  |  |  |             uncodedBlockSize = 57472; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         case DATVModSettings::FEC910: | 
					
						
							|  |  |  |             uncodedBlockSize = 58192; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         case DATVModSettings::FEC14: | 
					
						
							|  |  |  |             uncodedBlockSize = 16008; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         case DATVModSettings::FEC13: | 
					
						
							|  |  |  |             uncodedBlockSize = 21408; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         case DATVModSettings::FEC25: | 
					
						
							|  |  |  |             uncodedBlockSize = 25728; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         case DATVModSettings::FEC35: | 
					
						
							|  |  |  |             uncodedBlockSize = 38688; | 
					
						
							|  |  |  |             break; | 
					
						
							| 
									
										
										
										
											2021-03-31 17:01:47 +01:00
										 |  |  |         default: | 
					
						
							|  |  |  |             qDebug() << "DATVModSource::getDVBSDataBitrate: Unsupported DVB-S2 code rate"; | 
					
						
							|  |  |  |             break; | 
					
						
							| 
									
										
										
										
											2021-03-31 16:41:42 +01:00
										 |  |  |         } | 
					
						
							|  |  |  |         fecFactor = (uncodedBlockSize-bbHeaderBits)/(float)codedBlockSize; | 
					
						
							|  |  |  |         float symbolsPerFrame = codedBlockSize/bitsPerSymbol; | 
					
						
							|  |  |  |         // 90 symbols for PL header
 | 
					
						
							|  |  |  |         plFactor = symbolsPerFrame / (symbolsPerFrame + 90.0f); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return std::round(settings.m_symbolRate * bitsPerSymbol * fecFactor * plFactor); | 
					
						
							| 
									
										
										
										
											2021-03-18 17:17:58 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void DATVModSource::checkBitrates() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     int dataBitrate = getDVBSDataBitrate(m_settings); | 
					
						
							|  |  |  |     qDebug() << "MPEG-TS bitrate: " << m_mpegTSBitrate; | 
					
						
							| 
									
										
										
										
											2021-03-31 16:41:42 +01:00
										 |  |  |     qDebug() << "DVB data bitrate: " << dataBitrate; | 
					
						
							| 
									
										
										
										
											2021-03-18 17:17:58 +00:00
										 |  |  |     if (dataBitrate < m_mpegTSBitrate) | 
					
						
							| 
									
										
										
										
											2021-03-31 16:41:42 +01:00
										 |  |  |         qWarning() << "DVB data bitrate is lower than the bitrate of the MPEG transport stream"; | 
					
						
							| 
									
										
										
										
											2021-03-18 17:17:58 +00:00
										 |  |  |     m_tsRatio = m_mpegTSBitrate/(float)dataBitrate; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | DATVModSource::DATVModSource() : | 
					
						
							| 
									
										
										
										
											2021-10-20 23:01:44 +02:00
										 |  |  |     m_mpegTSBitrate(0), | 
					
						
							|  |  |  |     m_mpegTSSize(0), | 
					
						
							| 
									
										
										
										
											2021-03-18 17:17:58 +00:00
										 |  |  |     m_sampleIdx(0), | 
					
						
							|  |  |  |     m_frameIdx(0), | 
					
						
							|  |  |  |     m_frameCount(0), | 
					
						
							|  |  |  |     m_tsRatio(0.0f), | 
					
						
							|  |  |  |     m_symbolCount(0), | 
					
						
							|  |  |  |     m_symbolSel(0), | 
					
						
							|  |  |  |     m_symbolIdx(0), | 
					
						
							|  |  |  |     m_samplesPerSymbol(1), | 
					
						
							|  |  |  |     m_udpSocket(nullptr), | 
					
						
							|  |  |  |     m_udpByteCount(0), | 
					
						
							| 
									
										
										
										
											2021-10-20 23:01:44 +02:00
										 |  |  |     m_udpAbsByteCount(0), | 
					
						
							| 
									
										
										
										
											2021-03-18 17:17:58 +00:00
										 |  |  |     m_udpBufferIdx(0), | 
					
						
							|  |  |  |     m_udpBufferCount(0), | 
					
						
							| 
									
										
										
										
											2021-07-28 16:10:04 +01:00
										 |  |  |     m_udpMaxBufferUtilization(0), | 
					
						
							| 
									
										
										
										
											2021-03-18 17:17:58 +00:00
										 |  |  |     m_sampleRate(0), | 
					
						
							|  |  |  |     m_channelSampleRate(1000000), | 
					
						
							|  |  |  |     m_channelFrequencyOffset(0), | 
					
						
							|  |  |  |     m_tsFileOK(false), | 
					
						
							|  |  |  |     m_messageQueueToGUI(nullptr) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     m_interpolatorDistanceRemain = 0.0f; | 
					
						
							|  |  |  |     m_interpolatorDistance = 1.0f; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     applyChannelSettings(m_channelSampleRate, m_channelFrequencyOffset, true); | 
					
						
							|  |  |  |     applySettings(m_settings, true); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | DATVModSource::~DATVModSource() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void DATVModSource::pull(SampleVector::iterator begin, unsigned int nbSamples) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     std::for_each( | 
					
						
							|  |  |  |         begin, | 
					
						
							|  |  |  |         begin + nbSamples, | 
					
						
							|  |  |  |         [this](Sample& s) { | 
					
						
							|  |  |  |             pullOne(s); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     ); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void DATVModSource::prefetch(unsigned int nbSamples) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     (void) nbSamples; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void DATVModSource::pullOne(Sample& sample) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (m_settings.m_channelMute) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         sample.m_real = 0.0f; | 
					
						
							|  |  |  |         sample.m_imag = 0.0f; | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Complex ci; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (m_sampleRate == m_channelSampleRate) // no interpolation nor decimation
 | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         modulateSample(); | 
					
						
							|  |  |  |         pullFinalize(m_modSample, sample); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         if (m_interpolatorDistance > 1.0f) // decimate
 | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             modulateSample(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             while (!m_interpolator.decimate(&m_interpolatorDistanceRemain, m_modSample, &ci)) | 
					
						
							|  |  |  |                 modulateSample(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             if (m_interpolator.interpolate(&m_interpolatorDistanceRemain, m_modSample, &ci)) | 
					
						
							|  |  |  |                 modulateSample(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         m_interpolatorDistanceRemain += m_interpolatorDistance; | 
					
						
							|  |  |  |         pullFinalize(ci, sample); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void DATVModSource::pullFinalize(Complex& ci, Sample& sample) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     ci *= m_carrierNco.nextIQ(); // shift to carrier frequency
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     double magsq = ci.real() * ci.real() + ci.imag() * ci.imag(); | 
					
						
							|  |  |  |     m_movingAverage(magsq); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     sample.m_real = (FixReal) (ci.real() * SDR_TX_SCALEF); | 
					
						
							|  |  |  |     sample.m_imag = (FixReal) (ci.imag() * SDR_TX_SCALEF); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void DATVModSource::modulateSample() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     Real i, q; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (m_sampleIdx == 0) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         while (m_symbolCount == 0) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             bool tsFileReady = (m_settings.m_source == DATVModSettings::SourceFile) | 
					
						
							| 
									
										
										
										
											2021-04-01 08:06:41 +02:00
										 |  |  |                 && m_settings.m_tsFilePlay | 
					
						
							|  |  |  |                 && m_tsFileOK | 
					
						
							|  |  |  |                 && !m_mpegTSStream.eof(); | 
					
						
							| 
									
										
										
										
											2021-03-18 17:17:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-01 08:06:41 +02:00
										 |  |  |             if (tsFileReady | 
					
						
							| 
									
										
										
										
											2021-03-18 17:17:58 +00:00
										 |  |  |                 && (m_frameIdx/(m_frameCount+1.0f) < m_tsRatio)  // Insert null packets if file rate is lower than DVB-S data rate
 | 
					
						
							| 
									
										
										
										
											2021-04-01 08:06:41 +02:00
										 |  |  |             ) | 
					
						
							| 
									
										
										
										
											2021-03-18 17:17:58 +00:00
										 |  |  |             { | 
					
						
							|  |  |  |                 // Read transport stream packet from file
 | 
					
						
							|  |  |  |                 m_mpegTSStream.read((char *)m_mpegTS, sizeof(m_mpegTS)); | 
					
						
							|  |  |  |                 m_frameIdx++; | 
					
						
							|  |  |  |                 m_frameCount++; | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2021-04-01 08:06:41 +02:00
										 |  |  |             else if ((m_settings.m_source == DATVModSettings::SourceUDP) | 
					
						
							|  |  |  |                 && (m_udpBufferIdx < m_udpBufferCount) | 
					
						
							|  |  |  |             ) | 
					
						
							| 
									
										
										
										
											2021-03-18 17:17:58 +00:00
										 |  |  |             { | 
					
						
							|  |  |  |                 // Copy transport stream packet from UDP buffer
 | 
					
						
							|  |  |  |                 memcpy(m_mpegTS, &m_udpBuffer[m_udpBufferIdx*sizeof(m_mpegTS)], sizeof(m_mpegTS)); | 
					
						
							|  |  |  |                 m_udpBufferIdx++; | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2021-04-01 08:06:41 +02:00
										 |  |  |             else if ((m_settings.m_source == DATVModSettings::SourceUDP) | 
					
						
							|  |  |  |                 && ((m_udpSocket != nullptr) && m_udpSocket->hasPendingDatagrams()) | 
					
						
							|  |  |  |             ) | 
					
						
							| 
									
										
										
										
											2021-03-18 17:17:58 +00:00
										 |  |  |             { | 
					
						
							| 
									
										
										
										
											2021-07-28 16:10:04 +01:00
										 |  |  |                 updateUDPBufferUtilization(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-18 17:17:58 +00:00
										 |  |  |                 // Get transport stream packets from UDP - buffer if more than one
 | 
					
						
							|  |  |  |                 QNetworkDatagram datagram = m_udpSocket->receiveDatagram(); | 
					
						
							|  |  |  |                 QByteArray ba = datagram.data(); | 
					
						
							|  |  |  |                 int size = ba.size(); | 
					
						
							|  |  |  |                 char *data = ba.data(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-18 20:33:52 +00:00
										 |  |  |                 if (size <= (int)sizeof(m_udpBuffer)) | 
					
						
							| 
									
										
										
										
											2021-03-18 17:17:58 +00:00
										 |  |  |                 { | 
					
						
							|  |  |  |                     memcpy(m_mpegTS, data, sizeof(m_mpegTS)); | 
					
						
							| 
									
										
										
										
											2021-04-01 08:06:41 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |                     if (size >= (int)sizeof(m_mpegTS)) { | 
					
						
							| 
									
										
										
										
											2021-03-18 17:17:58 +00:00
										 |  |  |                         memcpy(&m_udpBuffer[0], &data[sizeof(m_mpegTS)], size - sizeof(m_mpegTS)); | 
					
						
							| 
									
										
										
										
											2021-04-01 08:06:41 +02:00
										 |  |  |                     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-18 17:17:58 +00:00
										 |  |  |                     m_udpBufferIdx = 0; | 
					
						
							|  |  |  |                     m_udpBufferCount = (size / sizeof(m_mpegTS)) - 1; | 
					
						
							| 
									
										
										
										
											2021-04-01 08:06:41 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |                     if (size % sizeof(m_mpegTS) != 0) { | 
					
						
							| 
									
										
										
										
											2021-03-18 17:17:58 +00:00
										 |  |  |                         qWarning() << "DATVModSource::modulateSample: UDP packet size (" << size << ") is not a multiple of " << sizeof(m_mpegTS); | 
					
						
							| 
									
										
										
										
											2021-04-01 08:06:41 +02:00
										 |  |  |                     } | 
					
						
							| 
									
										
										
										
											2021-03-18 17:17:58 +00:00
										 |  |  |                 } | 
					
						
							|  |  |  |                 else | 
					
						
							| 
									
										
										
										
											2021-04-01 08:06:41 +02:00
										 |  |  |                 { | 
					
						
							| 
									
										
										
										
											2021-03-18 17:17:58 +00:00
										 |  |  |                     qWarning() << "DATVModSource::modulateSample: UDP packet size (" << size << ") exceeds buffer size " << sizeof(m_udpBuffer) << ")"; | 
					
						
							| 
									
										
										
										
											2021-04-01 08:06:41 +02:00
										 |  |  |                 } | 
					
						
							| 
									
										
										
										
											2021-03-18 17:17:58 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |                 m_udpByteCount += ba.size(); | 
					
						
							| 
									
										
										
										
											2021-10-20 23:01:44 +02:00
										 |  |  |                 m_udpAbsByteCount += ba.size(); | 
					
						
							| 
									
										
										
										
											2021-03-18 17:17:58 +00:00
										 |  |  |             } | 
					
						
							|  |  |  |             else | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 // Insert null packet. PID=0x1fff
 | 
					
						
							|  |  |  |                 memset(m_mpegTS, 0, sizeof(m_mpegTS)); | 
					
						
							|  |  |  |                 m_mpegTS[0] = 0x47; // Sync byte
 | 
					
						
							|  |  |  |                 m_mpegTS[1] = 0x01; | 
					
						
							|  |  |  |                 m_mpegTS[2] = 0xff; | 
					
						
							|  |  |  |                 m_mpegTS[3] = 0xff; | 
					
						
							|  |  |  |                 m_mpegTS[4] = 0x10; | 
					
						
							| 
									
										
										
										
											2021-04-01 08:06:41 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |                 if (tsFileReady) { | 
					
						
							| 
									
										
										
										
											2021-03-18 17:17:58 +00:00
										 |  |  |                     m_frameCount++; | 
					
						
							| 
									
										
										
										
											2021-04-01 08:06:41 +02:00
										 |  |  |                 } | 
					
						
							| 
									
										
										
										
											2021-03-18 17:17:58 +00:00
										 |  |  |                 //qDebug() << "null " << tsFileReady << " " << (m_frameIdx/(m_frameCount+1.0f)) << " " << m_tsRatio;
 | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (m_settings.m_standard == DATVModSettings::DVB_S) | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 // Encode using DVB-S
 | 
					
						
							|  |  |  |                 m_symbolCount = m_dvbs.encode(m_mpegTS, m_iqSymbols); | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2021-03-31 16:41:42 +01:00
										 |  |  |             else | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 // Encode using DVB-S2
 | 
					
						
							|  |  |  |                 m_symbolCount = m_dvbs2.s2_add_ts_frame((u8 *)m_mpegTS); | 
					
						
							|  |  |  |                 m_plFrame = m_dvbs2.pl_get_frame(); | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2021-03-18 17:17:58 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |             // Loop file if we reach the end
 | 
					
						
							| 
									
										
										
										
											2021-04-01 08:06:41 +02:00
										 |  |  |             if ((m_settings.m_source == DATVModSettings::SourceFile) | 
					
						
							|  |  |  |                 && (m_frameIdx*DVBS::tsPacketLen >= m_mpegTSSize) | 
					
						
							|  |  |  |                 && m_settings.m_tsFilePlayLoop | 
					
						
							|  |  |  |             ) | 
					
						
							| 
									
										
										
										
											2021-03-18 17:17:58 +00:00
										 |  |  |             { | 
					
						
							| 
									
										
										
										
											2021-04-01 08:06:41 +02:00
										 |  |  |                 m_mpegTSStream.clear(); | 
					
						
							|  |  |  |                 m_mpegTSStream.seekg(0, std::ios::beg); | 
					
						
							| 
									
										
										
										
											2021-03-18 17:17:58 +00:00
										 |  |  |                 m_frameIdx = 0; | 
					
						
							|  |  |  |                 m_frameCount = 0; | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2021-04-01 08:06:41 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-18 17:17:58 +00:00
										 |  |  |             m_symbolIdx = 0; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (m_settings.m_modulation == DATVModSettings::BPSK) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             // BPSK
 | 
					
						
							|  |  |  |             i = m_pulseShapeI.filter(m_iqSymbols[m_symbolIdx*2+m_symbolSel] ? -1.0f : 1.0f); | 
					
						
							|  |  |  |             q = 0.0f; | 
					
						
							| 
									
										
										
										
											2021-04-01 08:06:41 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-18 17:17:58 +00:00
										 |  |  |             if (m_symbolSel == 1) | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 m_symbolIdx++; | 
					
						
							|  |  |  |                 m_symbolCount--; | 
					
						
							|  |  |  |                 m_symbolSel = 0; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             else | 
					
						
							| 
									
										
										
										
											2021-04-01 08:06:41 +02:00
										 |  |  |             { | 
					
						
							| 
									
										
										
										
											2021-03-18 17:17:58 +00:00
										 |  |  |                 m_symbolSel++; | 
					
						
							| 
									
										
										
										
											2021-04-01 08:06:41 +02:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2021-03-18 17:17:58 +00:00
										 |  |  |         } | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             // QPSK
 | 
					
						
							|  |  |  |             if (m_settings.m_standard == DATVModSettings::DVB_S) | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 // Does the 45-degree rotation matter?
 | 
					
						
							|  |  |  |                 // Makes a little difference to amplitude of filter output, but we could scale that
 | 
					
						
							|  |  |  |                 i = m_pulseShapeI.filter(m_iqSymbols[m_symbolIdx*2] ? -1.0f : 1.0f); | 
					
						
							|  |  |  |                 q = m_pulseShapeQ.filter(m_iqSymbols[m_symbolIdx*2+1] ? -1.0f : 1.0f); | 
					
						
							|  |  |  |                 /*
 | 
					
						
							|  |  |  |                 int sym = (m_iqSymbols[m_symbolIdx*2] << 1) | m_iqSymbols[m_symbolIdx*2+1]; | 
					
						
							|  |  |  |                 if (sym == 0) | 
					
						
							|  |  |  |                 { | 
					
						
							|  |  |  |                     i = m_pulseShapeI.filter(cos(M_PI/4)); | 
					
						
							|  |  |  |                     q = m_pulseShapeQ.filter(sin(M_PI/4)); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 else if (sym == 1) | 
					
						
							|  |  |  |                 { | 
					
						
							|  |  |  |                     i = m_pulseShapeI.filter(cos(7*M_PI/4)); | 
					
						
							|  |  |  |                     q = m_pulseShapeQ.filter(sin(7*M_PI/4)); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 else if (sym == 2) | 
					
						
							|  |  |  |                 { | 
					
						
							|  |  |  |                     i = m_pulseShapeI.filter(cos(3*M_PI/4)); | 
					
						
							|  |  |  |                     q = m_pulseShapeQ.filter(sin(3*M_PI/4)); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 else if (sym == 3) | 
					
						
							|  |  |  |                 { | 
					
						
							|  |  |  |                     i = m_pulseShapeI.filter(cos(5*M_PI/4)); | 
					
						
							|  |  |  |                     q = m_pulseShapeQ.filter(sin(5*M_PI/4)); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 */ | 
					
						
							| 
									
										
										
										
											2021-03-31 16:41:42 +01:00
										 |  |  |                 m_symbolIdx++; | 
					
						
							|  |  |  |                 m_symbolCount--; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             else | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 // First 90 symbols of DVB-S2 are pi/2 BPSK, then remaining symbols are in specified modulation
 | 
					
						
							|  |  |  |                 i = m_pulseShapeI.filter(m_plFrame[m_symbolIdx].re/32767.0); | 
					
						
							|  |  |  |                 q = m_pulseShapeQ.filter(m_plFrame[m_symbolIdx].im/32767.0); | 
					
						
							|  |  |  |                 m_symbolIdx++; | 
					
						
							|  |  |  |                 m_symbolCount--; | 
					
						
							| 
									
										
										
										
											2021-03-18 17:17:58 +00:00
										 |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         i = m_pulseShapeI.filter(0.0f); | 
					
						
							|  |  |  |         q = m_pulseShapeQ.filter(0.0f); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-04-01 08:06:41 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-18 17:17:58 +00:00
										 |  |  |     m_sampleIdx++; | 
					
						
							| 
									
										
										
										
											2021-04-01 08:06:41 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (m_sampleIdx >= m_samplesPerSymbol) { | 
					
						
							| 
									
										
										
										
											2021-03-18 17:17:58 +00:00
										 |  |  |         m_sampleIdx = 0; | 
					
						
							| 
									
										
										
										
											2021-04-01 08:06:41 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-03-18 17:17:58 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     m_modSample.real(i); | 
					
						
							|  |  |  |     m_modSample.imag(q); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // These levels aren't currently used in the GUI
 | 
					
						
							|  |  |  |     Real t = std::abs(m_modSample); | 
					
						
							|  |  |  |     calculateLevel(t); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void DATVModSource::calculateLevel(Real& sample) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (m_levelCalcCount < m_levelNbSamples) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         m_peakLevel = std::max(std::fabs(m_peakLevel), sample); | 
					
						
							|  |  |  |         m_levelSum += sample * sample; | 
					
						
							|  |  |  |         m_levelCalcCount++; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         m_rmsLevel = std::sqrt(m_levelSum / m_levelNbSamples); | 
					
						
							|  |  |  |         m_peakLevelOut = m_peakLevel; | 
					
						
							|  |  |  |         m_peakLevel = 0.0f; | 
					
						
							|  |  |  |         m_levelSum = 0.0f; | 
					
						
							|  |  |  |         m_levelCalcCount = 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void DATVModSource::openTsFile(const QString& fileName) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     m_tsFileOK = false; | 
					
						
							|  |  |  |     m_mpegTSBitrate = getTSBitrate(fileName); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (m_mpegTSBitrate > 0) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         m_mpegTSStream.open(qPrintable(fileName), std::ifstream::binary); | 
					
						
							|  |  |  |         if (m_mpegTSStream.is_open()) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             m_mpegTSStream.seekg (0, m_mpegTSStream.end); | 
					
						
							|  |  |  |             m_mpegTSSize = m_mpegTSStream.tellg(); | 
					
						
							|  |  |  |             m_mpegTSStream.seekg (0, m_mpegTSStream.beg); | 
					
						
							|  |  |  |             m_frameIdx = 0; | 
					
						
							|  |  |  |             m_frameCount = 0; | 
					
						
							|  |  |  |             m_tsFileOK = true; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         checkBitrates(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |         qDebug() << "DATVModSource::openTsFile: Failed to get bitrate for transport stream file: " << fileName; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (m_tsFileOK) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         m_settings.m_tsFileName = fileName; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (getMessageQueueToGUI()) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             DATVModReport::MsgReportTsFileSourceStreamData *report; | 
					
						
							|  |  |  |             report = DATVModReport::MsgReportTsFileSourceStreamData::create(m_mpegTSBitrate, m_mpegTSSize); | 
					
						
							|  |  |  |             getMessageQueueToGUI()->push(report); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         m_settings.m_tsFileName.clear(); | 
					
						
							|  |  |  |         qDebug() << "DATVModSource::openTsFile: Cannot open file: " << fileName; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void DATVModSource::seekTsFileStream(int seekPercentage) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (m_tsFileOK) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         m_frameIdx = ((m_mpegTSSize / DVBS::tsPacketLen) * seekPercentage) / 100; | 
					
						
							|  |  |  |         m_mpegTSStream.seekg (m_frameIdx * (std::streampos)DVBS::tsPacketLen, m_mpegTSStream.beg); | 
					
						
							|  |  |  |         m_frameCount = (int)(m_frameIdx / m_tsRatio); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void DATVModSource::reportTsFileSourceStreamTiming() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     int framesCount = m_tsFileOK ? m_frameIdx : 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (getMessageQueueToGUI()) | 
					
						
							|  |  |  |         getMessageQueueToGUI()->push(DATVModReport::MsgReportTsFileSourceStreamTiming::create(framesCount)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void DATVModSource::reportUDPBitrate() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     boost::chrono::duration<double> sec = boost::chrono::steady_clock::now() - m_udpTimingStart; | 
					
						
							|  |  |  |     double seconds = sec.count(); | 
					
						
							|  |  |  |     int bitrate = seconds > 0.0 ? m_udpByteCount * 8 / seconds : 0; | 
					
						
							|  |  |  |     m_udpTimingStart = boost::chrono::steady_clock::now(); | 
					
						
							|  |  |  |     m_udpByteCount = 0; | 
					
						
							| 
									
										
										
										
											2021-10-20 23:01:44 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (getMessageQueueToGUI()) { | 
					
						
							|  |  |  |         getMessageQueueToGUI()->push(DATVModReport::MsgReportUDPBitrate::create(bitrate)); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-03-18 17:17:58 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-28 16:10:04 +01:00
										 |  |  | void DATVModSource::updateUDPBufferUtilization() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | #ifdef _WIN32
 | 
					
						
							|  |  |  |     u_long count; | 
					
						
							|  |  |  |     ioctlsocket(m_udpSocket->socketDescriptor(), FIONREAD, &count); | 
					
						
							|  |  |  |     if (count > m_udpMaxBufferUtilization) { | 
					
						
							|  |  |  |         m_udpMaxBufferUtilization = count; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  |     // On linux, ioctl(s, SIOCINQ, &count); only returns length of first datagram, so we can't support this
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void DATVModSource::reportUDPBufferUtilization() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     // Report maximum utilization since last call
 | 
					
						
							|  |  |  |     updateUDPBufferUtilization(); | 
					
						
							| 
									
										
										
										
											2021-10-20 23:01:44 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-28 16:10:04 +01:00
										 |  |  |     if (getMessageQueueToGUI()) | 
					
						
							| 
									
										
										
										
											2021-10-20 23:01:44 +02:00
										 |  |  |     { | 
					
						
							|  |  |  |         getMessageQueueToGUI()->push(DATVModReport::MsgReportUDPBufferUtilization::create( | 
					
						
							|  |  |  |             m_udpMaxBufferUtilization / (float)DATVModSettings::m_udpBufferSize * 100.0)); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-28 16:10:04 +01:00
										 |  |  |     m_udpMaxBufferUtilization = 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-18 17:17:58 +00:00
										 |  |  | void DATVModSource::applyChannelSettings(int channelSampleRate, int channelFrequencyOffset, bool force) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     qDebug() << "DATVModSource::applyChannelSettings:" | 
					
						
							|  |  |  |             << " channelSampleRate: " << channelSampleRate | 
					
						
							|  |  |  |             << " channelFrequencyOffset: " << channelFrequencyOffset; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ((channelFrequencyOffset != m_channelFrequencyOffset) || | 
					
						
							|  |  |  |         (channelSampleRate != m_channelSampleRate) || force) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         m_carrierNco.setFreq(channelFrequencyOffset, channelSampleRate); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ((channelSampleRate != m_channelSampleRate) || force) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2021-04-17 12:55:30 +01:00
										 |  |  |         if (m_settings.m_symbolRate > 0) | 
					
						
							| 
									
										
										
										
											2021-03-18 17:17:58 +00:00
										 |  |  |         { | 
					
						
							| 
									
										
										
										
											2021-04-17 12:55:30 +01:00
										 |  |  |             m_sampleRate = (channelSampleRate/m_settings.m_symbolRate)*m_settings.m_symbolRate; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             // Create interpolator if not integer multiple
 | 
					
						
							|  |  |  |             if (m_sampleRate != channelSampleRate) | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 m_interpolatorDistanceRemain = 0; | 
					
						
							|  |  |  |                 m_interpolatorDistance = (Real) m_sampleRate / (Real) channelSampleRate; | 
					
						
							|  |  |  |                 m_interpolator.create(32, m_sampleRate, m_settings.m_rfBandwidth / 2.2f, 3.0); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             if (getMessageQueueToGUI()) | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 getMessageQueueToGUI()->push(DATVModReport::MsgReportRates::create( | 
					
						
							| 
									
										
										
										
											2021-10-20 23:01:44 +02:00
										 |  |  |                     channelSampleRate, | 
					
						
							|  |  |  |                     m_sampleRate, | 
					
						
							|  |  |  |                     getDVBSDataBitrate(m_settings))); | 
					
						
							| 
									
										
										
										
											2021-04-17 12:55:30 +01:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2021-03-18 17:17:58 +00:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     m_channelSampleRate = channelSampleRate; | 
					
						
							|  |  |  |     m_channelFrequencyOffset = channelFrequencyOffset; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-17 12:55:30 +01:00
										 |  |  |     if (m_settings.m_symbolRate > 0) | 
					
						
							|  |  |  |         m_samplesPerSymbol = m_channelSampleRate/m_settings.m_symbolRate; | 
					
						
							| 
									
										
										
										
											2021-03-18 17:17:58 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     m_pulseShapeI.create(m_settings.m_rollOff, 8, m_samplesPerSymbol, false); | 
					
						
							|  |  |  |     m_pulseShapeQ.create(m_settings.m_rollOff, 8, m_samplesPerSymbol, false); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void DATVModSource::applySettings(const DATVModSettings& settings, bool force) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     qDebug() << "DATVModSource::applySettings:" | 
					
						
							|  |  |  |             << " m_inputFrequencyOffset: " << settings.m_inputFrequencyOffset | 
					
						
							|  |  |  |             << " m_rfBandwidth: " << settings.m_rfBandwidth | 
					
						
							|  |  |  |             << " m_source: " << (int) settings.m_source | 
					
						
							|  |  |  |             << " m_standard: " << (int) settings.m_standard | 
					
						
							|  |  |  |             << " m_modulation: " << (int) settings.m_modulation | 
					
						
							|  |  |  |             << " m_fec: " << (int) settings.m_fec | 
					
						
							|  |  |  |             << " m_symbolRate: " << (int) settings.m_symbolRate | 
					
						
							|  |  |  |             << " m_rollOff: " << (int) settings.m_rollOff | 
					
						
							|  |  |  |             << " m_tsFilePlayLoop: " << settings.m_tsFilePlayLoop | 
					
						
							|  |  |  |             << " m_tsFilePlay: " << settings.m_tsFilePlay | 
					
						
							|  |  |  |             << " m_udpAddress: " << settings.m_udpAddress | 
					
						
							|  |  |  |             << " m_udpPort: " << settings.m_udpPort | 
					
						
							|  |  |  |             << " m_channelMute: " << settings.m_channelMute | 
					
						
							|  |  |  |             << " force: " << force; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ((settings.m_rfBandwidth != m_settings.m_rfBandwidth) | 
					
						
							|  |  |  |         || (settings.m_modulation != m_settings.m_modulation) | 
					
						
							|  |  |  |         || (settings.m_symbolRate != m_settings.m_symbolRate) | 
					
						
							|  |  |  |         || force) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2021-04-17 12:55:30 +01:00
										 |  |  |         if (settings.m_symbolRate > 0) | 
					
						
							| 
									
										
										
										
											2021-03-18 17:17:58 +00:00
										 |  |  |         { | 
					
						
							| 
									
										
										
										
											2021-04-17 12:55:30 +01:00
										 |  |  |             m_sampleRate = (m_channelSampleRate/settings.m_symbolRate)*settings.m_symbolRate; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (m_sampleRate != m_channelSampleRate) | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 m_interpolatorDistanceRemain = 0; | 
					
						
							|  |  |  |                 m_interpolatorDistance = (Real) m_sampleRate / (Real) m_channelSampleRate; | 
					
						
							|  |  |  |                 m_interpolator.create(32, m_sampleRate, settings.m_rfBandwidth / 2.2f, 3.0); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             if (getMessageQueueToGUI()) | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 getMessageQueueToGUI()->push(DATVModReport::MsgReportRates::create( | 
					
						
							|  |  |  |                                                     m_channelSampleRate, m_sampleRate, | 
					
						
							|  |  |  |                                                     getDVBSDataBitrate(settings))); | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2021-03-18 17:17:58 +00:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-04-17 12:55:30 +01:00
										 |  |  |         else | 
					
						
							|  |  |  |             qWarning() << "DATVModSource::applySettings: symbolRate must be greater than 0."; | 
					
						
							| 
									
										
										
										
											2021-03-18 17:17:58 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ((settings.m_source != m_settings.m_source) | 
					
						
							|  |  |  |         || (settings.m_udpAddress != m_settings.m_udpAddress) | 
					
						
							|  |  |  |         || (settings.m_udpPort != m_settings.m_udpPort) | 
					
						
							|  |  |  |         || force) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         if (m_udpSocket) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             m_udpSocket->close(); | 
					
						
							|  |  |  |             delete m_udpSocket; | 
					
						
							|  |  |  |             m_udpSocket = nullptr; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (settings.m_source == DATVModSettings::SourceUDP) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             m_udpSocket = new QUdpSocket(); | 
					
						
							|  |  |  |             m_udpSocket->bind(QHostAddress(settings.m_udpAddress), settings.m_udpPort); | 
					
						
							| 
									
										
										
										
											2021-07-28 16:10:04 +01:00
										 |  |  |             m_udpSocket->setSocketOption(QAbstractSocket::ReceiveBufferSizeSocketOption, DATVModSettings::m_udpBufferSize); | 
					
						
							| 
									
										
										
										
											2021-03-18 17:17:58 +00:00
										 |  |  |             m_udpTimingStart = boost::chrono::steady_clock::now(); | 
					
						
							|  |  |  |             m_udpByteCount = 0; | 
					
						
							| 
									
										
										
										
											2021-10-20 23:01:44 +02:00
										 |  |  |             m_udpAbsByteCount = 0; | 
					
						
							| 
									
										
										
										
											2021-03-18 17:17:58 +00:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ((settings.m_standard != m_settings.m_standard) | 
					
						
							|  |  |  |         || (settings.m_modulation != m_settings.m_modulation) | 
					
						
							|  |  |  |         || force) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         m_symbolSel = 0; | 
					
						
							|  |  |  |         m_symbolIdx = 0; | 
					
						
							|  |  |  |         m_symbolCount = 0; | 
					
						
							|  |  |  |         m_sampleIdx = 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ((settings.m_standard != m_settings.m_standard) | 
					
						
							|  |  |  |         || (settings.m_modulation != m_settings.m_modulation) | 
					
						
							|  |  |  |         || (settings.m_fec != m_settings.m_fec) | 
					
						
							|  |  |  |         || (settings.m_rollOff != m_settings.m_rollOff) | 
					
						
							|  |  |  |         || force) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         if (settings.m_standard == DATVModSettings::DVB_S) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             switch (settings.m_fec) | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |             case DATVModSettings::FEC12: | 
					
						
							|  |  |  |                 m_dvbs.setCodeRate(DVBS::RATE_1_2); | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             case DATVModSettings::FEC23: | 
					
						
							|  |  |  |                 m_dvbs.setCodeRate(DVBS::RATE_2_3); | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             case DATVModSettings::FEC34: | 
					
						
							|  |  |  |                 m_dvbs.setCodeRate(DVBS::RATE_3_4); | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             case DATVModSettings::FEC56: | 
					
						
							|  |  |  |                 m_dvbs.setCodeRate(DVBS::RATE_5_6); | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             case DATVModSettings::FEC78: | 
					
						
							|  |  |  |                 m_dvbs.setCodeRate(DVBS::RATE_7_8); | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             default: | 
					
						
							|  |  |  |                 qCritical() << "DATVModSource::applySettings: Unsupported FEC code rate for DVB-S: " << settings.m_fec; | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-03-31 16:41:42 +01:00
										 |  |  |         else | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             m_dvbs2Format.frame_type = FRAME_NORMAL; | 
					
						
							|  |  |  |             m_dvbs2Format.pilots = 0; // PILOTS_OFF;
 | 
					
						
							|  |  |  |             m_dvbs2Format.dummy_frame = 0; | 
					
						
							|  |  |  |             m_dvbs2Format.null_deletion = 0; | 
					
						
							|  |  |  |             m_dvbs2Format.intface = M_ACM;  // Unused?
 | 
					
						
							|  |  |  |             m_dvbs2Format.broadcasting = 1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             switch (settings.m_modulation) | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |             case DATVModSettings::QPSK: | 
					
						
							|  |  |  |                 m_dvbs2Format.constellation = M_QPSK; | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             case DATVModSettings::PSK8: | 
					
						
							|  |  |  |                 m_dvbs2Format.constellation = M_8PSK; | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             case DATVModSettings::APSK16: | 
					
						
							|  |  |  |                 m_dvbs2Format.constellation = M_16APSK; | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             case DATVModSettings::APSK32: | 
					
						
							|  |  |  |                 m_dvbs2Format.constellation = M_32APSK; | 
					
						
							|  |  |  |                 break; | 
					
						
							| 
									
										
										
										
											2021-03-31 17:01:47 +01:00
										 |  |  |             default: | 
					
						
							|  |  |  |                 qDebug() << "DATVModSource::applySettings: Unsupported modulation for DVB-S2"; | 
					
						
							|  |  |  |                 break; | 
					
						
							| 
									
										
										
										
											2021-03-31 16:41:42 +01:00
										 |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             switch (settings.m_fec) | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |             case DATVModSettings::FEC12: | 
					
						
							|  |  |  |                 m_dvbs2Format.code_rate = CR_1_2; | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             case DATVModSettings::FEC23: | 
					
						
							|  |  |  |                 m_dvbs2Format.code_rate = CR_2_3; | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             case DATVModSettings::FEC34: | 
					
						
							|  |  |  |                 m_dvbs2Format.code_rate = CR_3_4; | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             case DATVModSettings::FEC56: | 
					
						
							|  |  |  |                 m_dvbs2Format.code_rate = CR_5_6; | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             case DATVModSettings::FEC45: | 
					
						
							|  |  |  |                 m_dvbs2Format.code_rate = CR_4_5; | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             case DATVModSettings::FEC89: | 
					
						
							|  |  |  |                 m_dvbs2Format.code_rate = CR_8_9; | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             case DATVModSettings::FEC910: | 
					
						
							|  |  |  |                 m_dvbs2Format.code_rate = CR_9_10; | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             case DATVModSettings::FEC14: | 
					
						
							|  |  |  |                 m_dvbs2Format.code_rate = CR_1_4; | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             case DATVModSettings::FEC13: | 
					
						
							|  |  |  |                 m_dvbs2Format.code_rate = CR_1_3; | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             case DATVModSettings::FEC25: | 
					
						
							|  |  |  |                 m_dvbs2Format.code_rate = CR_2_5; | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             case DATVModSettings::FEC35: | 
					
						
							|  |  |  |                 m_dvbs2Format.code_rate = CR_3_5; | 
					
						
							|  |  |  |                 break; | 
					
						
							| 
									
										
										
										
											2021-03-31 17:01:47 +01:00
										 |  |  |             default: | 
					
						
							|  |  |  |                 qDebug() << "DATVModSource::getDVBSDataBitrate: Unsupported code rate for DVB-S2"; | 
					
						
							|  |  |  |                 break; | 
					
						
							| 
									
										
										
										
											2021-03-31 16:41:42 +01:00
										 |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (settings.m_rollOff == 0.35f) | 
					
						
							|  |  |  |                 m_dvbs2Format.roll_off = RO_0_35; | 
					
						
							|  |  |  |             else if (settings.m_rollOff == 0.25f) | 
					
						
							|  |  |  |                 m_dvbs2Format.roll_off = RO_0_25; | 
					
						
							|  |  |  |             else | 
					
						
							|  |  |  |                 m_dvbs2Format.roll_off = RO_0_20; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             m_dvbs2.s2_set_configure(&m_dvbs2Format); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-03-18 17:17:58 +00:00
										 |  |  |         if (getMessageQueueToGUI()) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             getMessageQueueToGUI()->push(DATVModReport::MsgReportRates::create( | 
					
						
							|  |  |  |                                                 m_channelSampleRate, m_sampleRate, | 
					
						
							|  |  |  |                                                 getDVBSDataBitrate(settings))); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     m_settings = settings; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-17 12:55:30 +01:00
										 |  |  |     if (m_settings.m_symbolRate > 0) | 
					
						
							|  |  |  |         m_samplesPerSymbol = m_channelSampleRate/m_settings.m_symbolRate; | 
					
						
							| 
									
										
										
										
											2021-03-18 17:17:58 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     m_pulseShapeI.create(m_settings.m_rollOff, 8, m_samplesPerSymbol, false); | 
					
						
							|  |  |  |     m_pulseShapeQ.create(m_settings.m_rollOff, 8, m_samplesPerSymbol, false); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     checkBitrates(); | 
					
						
							|  |  |  | } |