Merge pull request #976 from srcejon/datvmod_udp_buf_util

DATV Mod: Add UDP buffer utilization in GUI on Windows
pull/981/head
Edouard Griffiths 2021-07-29 08:41:48 +02:00 zatwierdzone przez GitHub
commit 14e75232df
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 4AEE18F83AFDEB23
10 zmienionych plików z 118 dodań i 1 usunięć

Wyświetl plik

@ -52,6 +52,7 @@ MESSAGE_CLASS_DEFINITION(DATVMod::MsgConfigureTsFileName, Message)
MESSAGE_CLASS_DEFINITION(DATVMod::MsgConfigureTsFileSourceSeek, Message)
MESSAGE_CLASS_DEFINITION(DATVMod::MsgConfigureTsFileSourceStreamTiming, Message)
MESSAGE_CLASS_DEFINITION(DATVMod::MsgGetUDPBitrate, Message)
MESSAGE_CLASS_DEFINITION(DATVMod::MsgGetUDPBufferUtilization, Message)
const char* const DATVMod::m_channelIdURI = "sdrangel.channeltx.moddatv";
const char* const DATVMod::m_channelId = "DATVMod";
@ -185,6 +186,12 @@ bool DATVMod::handleMessage(const Message& cmd)
return true;
}
else if (MsgGetUDPBufferUtilization::match(cmd))
{
m_basebandSource->getInputMessageQueue()->push(DATVMod::MsgGetUDPBufferUtilization::create());
return true;
}
else
{
return false;

Wyświetl plik

@ -181,6 +181,23 @@ public:
{ }
};
class MsgGetUDPBufferUtilization : public Message {
MESSAGE_CLASS_DECLARATION
public:
static MsgGetUDPBufferUtilization* create()
{
return new MsgGetUDPBufferUtilization();
}
private:
MsgGetUDPBufferUtilization() :
Message()
{ }
};
//=================================================================
DATVMod(DeviceAPI *deviceAPI);

Wyświetl plik

@ -192,6 +192,11 @@ bool DATVModBaseband::handleMessage(const Message& cmd)
m_source.reportUDPBitrate();
return true;
}
else if (DATVMod::MsgGetUDPBufferUtilization::match(cmd))
{
m_source.reportUDPBufferUtilization();
return true;
}
else
{
return false;

Wyświetl plik

@ -98,6 +98,12 @@ DATVModGUI::DATVModGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, BasebandS
connect(getInputMessageQueue(), SIGNAL(messageEnqueued()), this, SLOT(handleSourceMessages()));
#ifndef _WIN32
// Only currently works on Windows, so hide on other OSes
ui->udpBufferUtilization->setVisible(false);
ui->udpBufferUtilizationLine->setVisible(false);
#endif
displaySettings();
applySettings(true);
if (!m_settings.m_tsFileName.isEmpty())
@ -174,6 +180,13 @@ bool DATVModGUI::handleMessage(const Message& message)
m_tickMsgOutstanding = false;
return true;
}
else if (DATVModReport::MsgReportUDPBufferUtilization::match(message))
{
DATVModReport::MsgReportUDPBufferUtilization& report = (DATVModReport::MsgReportUDPBufferUtilization&)message;
ui->udpBufferUtilization->setText(tr("%1%").arg(report.getUtilization(), 0, 'f', 1));
m_tickMsgOutstanding = false;
return true;
}
else if (DATVMod::MsgConfigureDATVMod::match(message))
{
const DATVMod::MsgConfigureDATVMod& cfg = (DATVMod::MsgConfigureDATVMod&) message;
@ -602,6 +615,7 @@ void DATVModGUI::tick()
{
m_tickMsgOutstanding = true;
m_datvMod->getInputMessageQueue()->push(DATVMod::MsgGetUDPBitrate::create());
m_datvMod->getInputMessageQueue()->push(DATVMod::MsgGetUDPBufferUtilization::create());
}
}
}

Wyświetl plik

@ -568,6 +568,23 @@
</property>
</widget>
</item>
<item>
<widget class="Line" name="udpBufferUtilizationLine">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="udpBufferUtilization">
<property name="toolTip">
<string>Indicates how full the UDP receive buffer is. If this reaches 100%, packets will likely be dropped.</string>
</property>
<property name="text">
<string>0%</string>
</property>
</widget>
</item>
</layout>
</item>
<item>

Wyświetl plik

@ -22,6 +22,7 @@ MESSAGE_CLASS_DEFINITION(DATVModReport::MsgReportTsFileSourceStreamTiming, Messa
MESSAGE_CLASS_DEFINITION(DATVModReport::MsgReportTsFileSourceStreamData, Message)
MESSAGE_CLASS_DEFINITION(DATVModReport::MsgReportRates, Message)
MESSAGE_CLASS_DEFINITION(DATVModReport::MsgReportUDPBitrate, Message)
MESSAGE_CLASS_DEFINITION(DATVModReport::MsgReportUDPBufferUtilization, Message)
DATVModReport::DATVModReport()
{ }

Wyświetl plik

@ -125,6 +125,27 @@ public:
{ }
};
class MsgReportUDPBufferUtilization : public Message
{
MESSAGE_CLASS_DECLARATION
public:
float getUtilization() const { return m_utilization; }
static MsgReportUDPBufferUtilization* create(int utilization)
{
return new MsgReportUDPBufferUtilization(utilization);
}
protected:
float m_utilization;
MsgReportUDPBufferUtilization(int utilization) :
Message(),
m_utilization(utilization)
{ }
};
public:
DATVModReport();
~DATVModReport();

Wyświetl plik

@ -108,6 +108,8 @@ struct DATVModSettings
static DATVModulation mapModulation(const QString& string);
static QString mapModulation(DATVModulation modulation);
static const int m_udpBufferSize = 5000000;
};
#endif /* PLUGINS_CHANNELTX_MODDATV_DATVMODSETTINGS_H_ */

Wyświetl plik

@ -43,6 +43,11 @@ extern "C"
#include "datvmodreport.h"
#include "datvmodsource.h"
#ifdef _WIN32
#include <winsock.h>
#pragma comment(lib, "Ws2_32.lib")
#endif
const int DATVModSource::m_levelNbSamples = 10000; // every 10ms
// Get transport stream bitrate from file
@ -223,6 +228,7 @@ DATVModSource::DATVModSource() :
m_udpByteCount(0),
m_udpBufferIdx(0),
m_udpBufferCount(0),
m_udpMaxBufferUtilization(0),
m_sampleRate(0),
m_channelSampleRate(1000000),
m_channelFrequencyOffset(0),
@ -337,6 +343,8 @@ void DATVModSource::modulateSample()
&& ((m_udpSocket != nullptr) && m_udpSocket->hasPendingDatagrams())
)
{
updateUDPBufferUtilization();
// Get transport stream packets from UDP - buffer if more than one
QNetworkDatagram datagram = m_udpSocket->receiveDatagram();
QByteArray ba = datagram.data();
@ -577,6 +585,28 @@ void DATVModSource::reportUDPBitrate()
m_udpByteCount = 0;
}
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();
if (getMessageQueueToGUI())
getMessageQueueToGUI()->push(DATVModReport::MsgReportUDPBufferUtilization::create(m_udpMaxBufferUtilization / (float)DATVModSettings::m_udpBufferSize * 100.0));
m_udpMaxBufferUtilization = 0;
}
void DATVModSource::applyChannelSettings(int channelSampleRate, int channelFrequencyOffset, bool force)
{
qDebug() << "DATVModSource::applyChannelSettings:"
@ -680,7 +710,7 @@ void DATVModSource::applySettings(const DATVModSettings& settings, bool force)
{
m_udpSocket = new QUdpSocket();
m_udpSocket->bind(QHostAddress(settings.m_udpAddress), settings.m_udpPort);
m_udpSocket->setSocketOption(QAbstractSocket::ReceiveBufferSizeSocketOption, 1000000);
m_udpSocket->setSocketOption(QAbstractSocket::ReceiveBufferSizeSocketOption, DATVModSettings::m_udpBufferSize);
m_udpTimingStart = boost::chrono::steady_clock::now();
m_udpByteCount = 0;
}

Wyświetl plik

@ -70,6 +70,7 @@ public:
void seekTsFileStream(int seekPercentage);
void reportTsFileSourceStreamTiming();
void reportUDPBitrate();
void reportUDPBufferUtilization();
private:
uint8_t m_mpegTS[188]; //!< MPEG transport stream packet
@ -99,6 +100,7 @@ private:
uint8_t m_udpBuffer[188*10];
int m_udpBufferIdx; //!< TS frame index into buffer
int m_udpBufferCount; //!< Number of TS frames in buffer
int m_udpMaxBufferUtilization;
int m_sampleRate;
int m_channelSampleRate;
@ -131,6 +133,7 @@ private:
int getTSBitrate(const QString& filename);
int getDVBSDataBitrate(const DATVModSettings& settings);
void checkBitrates();
void updateUDPBufferUtilization();
MessageQueue *getMessageQueueToGUI() { return m_messageQueueToGUI; }