1
0
mirror of https://github.com/f4exb/sdrangel.git synced 2024-11-22 08:04:49 -05:00

qrtplib: copy Audio to UDP/RTP: use a single UDP socket for UDP and RTP

This commit is contained in:
f4exb 2018-03-08 00:16:24 +01:00
parent f310eb4dad
commit 5b0f62c3e2
6 changed files with 103 additions and 63 deletions

View File

@ -48,6 +48,7 @@ RTPUDPTransmitter::RTPUDPTransmitter() :
m_init = false; m_init = false;
m_rtcpsock = 0; m_rtcpsock = 0;
m_rtpsock = 0; m_rtpsock = 0;
m_deletesocketswhendone = false;
m_waitingfordata = false; m_waitingfordata = false;
m_rtcpPort = 0; m_rtcpPort = 0;
m_rtpPort = 0; m_rtpPort = 0;
@ -122,15 +123,24 @@ int RTPUDPTransmitter::Create(std::size_t maximumpacketsize, const RTPTransmissi
} }
} }
m_rtpsock = new QUdpSocket(); if (params->GetUseExistingSockets(&m_rtpsock, &m_rtcpsock))
// If we're multiplexing, we're just going to set the RTCP socket to equal the RTP socket
if (params->GetRTCPMultiplexing())
{ {
m_rtcpsock = m_rtpsock; m_deletesocketswhendone = false;
m_rtcpPort = m_rtpPort; }
} else { else
m_rtcpsock = new QUdpSocket(); {
m_deletesocketswhendone = true;
m_rtpsock = new QUdpSocket();
// If we're multiplexing, we're just going to set the RTCP socket to equal the RTP socket
if (params->GetRTCPMultiplexing())
{
m_rtcpsock = m_rtpsock;
m_rtcpPort = m_rtpPort;
} else {
m_rtcpsock = new QUdpSocket();
}
} }
// set socket buffer sizes // set socket buffer sizes
@ -174,17 +184,6 @@ int RTPUDPTransmitter::BindSockets()
return 0; return 0;
} }
void RTPUDPTransmitter::moveToThread(QThread *thread)
{
if (m_rtpsock) {
m_rtpsock->moveToThread(thread);
}
if (m_rtpsock != m_rtcpsock) {
m_rtcpsock->moveToThread(thread);
}
}
void RTPUDPTransmitter::Destroy() void RTPUDPTransmitter::Destroy()
{ {
if (!m_init) { if (!m_init) {
@ -196,11 +195,14 @@ void RTPUDPTransmitter::Destroy()
return; return;
} }
if (m_rtpsock != m_rtcpsock) { if (m_deletesocketswhendone)
delete m_rtcpsock; {
} if (m_rtpsock != m_rtcpsock) {
delete m_rtcpsock;
}
delete m_rtpsock; delete m_rtpsock;
}
m_created = false; m_created = false;
} }

View File

@ -142,6 +142,16 @@ public:
m_forcedrtcpport = rtcpport; m_forcedrtcpport = rtcpport;
} }
/** Use sockets that have already been created, no checks on port numbers
* will be done, and no buffer sizes will be set; you'll need to close
* the sockets yourself when done, it will **not** be done automatically. */
void SetUseExistingSockets(QUdpSocket *rtpsocket, QUdpSocket *rtcpsocket)
{
m_rtpsock = rtpsocket;
m_rtcpsock = rtcpsocket;
m_useexistingsockets = true;
}
/** Returns the RTP socket's send buffer size. */ /** Returns the RTP socket's send buffer size. */
int GetRTPSendBufferSize() const int GetRTPSendBufferSize() const
{ {
@ -184,6 +194,20 @@ public:
return m_forcedrtcpport; return m_forcedrtcpport;
} }
/** Returns true and fills in sockets if existing sockets were set
* using RTPUDPv4TransmissionParams::SetUseExistingSockets. */
bool GetUseExistingSockets(QUdpSocket **rtpsocket, QUdpSocket **rtcpsocket) const
{
if (!m_useexistingsockets) {
return false;
}
*rtpsocket = m_rtpsock;
*rtcpsocket = m_rtcpsock;
return true;
}
private: private:
QHostAddress m_bindAddress; QHostAddress m_bindAddress;
QNetworkInterface m_mcastInterface; QNetworkInterface m_mcastInterface;
@ -195,6 +219,7 @@ private:
uint16_t m_forcedrtcpport; uint16_t m_forcedrtcpport;
QUdpSocket *m_rtpsock, *m_rtcpsock; QUdpSocket *m_rtpsock, *m_rtcpsock;
bool m_useexistingsockets;
}; };
inline RTPUDPTransmissionParams::RTPUDPTransmissionParams() : inline RTPUDPTransmissionParams::RTPUDPTransmissionParams() :
@ -210,6 +235,7 @@ inline RTPUDPTransmissionParams::RTPUDPTransmissionParams() :
m_forcedrtcpport = 0; m_forcedrtcpport = 0;
m_rtpsock = 0; m_rtpsock = 0;
m_rtcpsock = 0; m_rtcpsock = 0;
m_useexistingsockets = false;
} }
/** Additional information about the UDP over IPv4 transmitter. */ /** Additional information about the UDP over IPv4 transmitter. */
@ -321,6 +347,7 @@ private:
bool m_created; bool m_created;
bool m_waitingfordata; bool m_waitingfordata;
QUdpSocket *m_rtpsock, *m_rtcpsock; QUdpSocket *m_rtpsock, *m_rtcpsock;
bool m_deletesocketswhendone;
QHostAddress m_localIP; //!< from parameters bind IP QHostAddress m_localIP; //!< from parameters bind IP
QNetworkInterface m_multicastInterface; //!< from parameters multicast interface QNetworkInterface m_multicastInterface; //!< from parameters multicast interface
uint16_t m_rtpPort, m_rtcpPort; uint16_t m_rtpPort, m_rtcpPort;

View File

@ -16,34 +16,36 @@
/////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////
#include "audionetsink.h" #include "audionetsink.h"
#include "util/udpsink.h"
#include "util/rtpsink.h" #include "util/rtpsink.h"
#include <unistd.h>
#include <QUdpSocket>
const int AudioNetSink::m_udpBlockSize = 512; const int AudioNetSink::m_udpBlockSize = 512;
AudioNetSink::AudioNetSink(QObject *parent, bool stereo) : AudioNetSink::AudioNetSink(QObject *parent, bool stereo) :
m_type(SinkUDP), m_type(SinkUDP),
m_udpBufferAudioMono(0), m_rtpBufferAudio(0),
m_rtpBufferAudio(0) m_bufferIndex(0),
m_port(9998)
{ {
m_udpBufferAudioMono = new UDPSink<int16_t>(parent, m_udpBlockSize); m_udpSocket = new QUdpSocket(parent);
//m_rtpBufferAudio = new RTPSink("127.0.0.1", 9999, stereo ? RTPSink::PayloadL16Stereo : RTPSink::PayloadL16Mono); m_rtpBufferAudio = new RTPSink(m_udpSocket, stereo);
} }
AudioNetSink::~AudioNetSink() AudioNetSink::~AudioNetSink()
{ {
if (m_udpBufferAudioMono) {
delete m_udpBufferAudioMono;
}
if (m_rtpBufferAudio) { if (m_rtpBufferAudio) {
delete m_rtpBufferAudio; delete m_rtpBufferAudio;
} }
m_udpSocket->deleteLater(); // this thread is not the owner thread (was moved)
} }
//bool AudioNetSink::isRTPCapable() const bool AudioNetSink::isRTPCapable() const
//{ {
// return m_rtpBufferAudio->isValid(); return m_rtpBufferAudio->isValid();
//} }
bool AudioNetSink::selectType(SinkType type) bool AudioNetSink::selectType(SinkType type)
{ {
@ -65,9 +67,9 @@ bool AudioNetSink::selectType(SinkType type)
void AudioNetSink::setDestination(const QString& address, uint16_t port) void AudioNetSink::setDestination(const QString& address, uint16_t port)
{ {
if (m_udpBufferAudioMono) { m_address.setAddress(const_cast<QString&>(address));
m_udpBufferAudioMono->setDestination(address, port); m_port = port;
}
if (m_rtpBufferAudio) { if (m_rtpBufferAudio) {
m_rtpBufferAudio->setDestination(address, port); m_rtpBufferAudio->setDestination(address, port);
} }
@ -89,21 +91,28 @@ void AudioNetSink::deleteDestination(const QString& address, uint16_t port)
void AudioNetSink::write(qint16 sample) void AudioNetSink::write(qint16 sample)
{ {
if (m_type == SinkUDP) { if (m_type == SinkUDP)
m_udpBufferAudioMono->write(sample); {
} else if (m_type == SinkRTP) { if (m_bufferIndex >= m_udpBlockSize)
{
m_udpSocket->writeDatagram((const char*)m_data, (qint64 ) m_udpBlockSize, m_address, m_port);
m_bufferIndex = 0;
}
else
{
qint16 *p = (qint16*) &m_data[m_bufferIndex];
*p = sample;
m_bufferIndex += sizeof(qint16);
}
}
else if (m_type == SinkRTP)
{
m_rtpBufferAudio->write((uint8_t *) &sample); m_rtpBufferAudio->write((uint8_t *) &sample);
} }
} }
void AudioNetSink::moveToThread(QThread *thread) void AudioNetSink::moveToThread(QThread *thread)
{ {
if (m_udpBufferAudioMono) { m_udpSocket->moveToThread(thread);
m_udpBufferAudioMono->moveToThread(thread);
}
if (m_rtpBufferAudio) {
m_rtpBufferAudio->moveToThread(thread);
}
} }

View File

@ -21,10 +21,11 @@
#include "dsp/dsptypes.h" #include "dsp/dsptypes.h"
#include "util/export.h" #include "util/export.h"
#include <stdint.h>
#include <QObject> #include <QObject>
#include <QHostAddress>
#include <stdint.h>
template<typename T> class UDPSink; class QUdpSocket;
class RTPSink; class RTPSink;
class QThread; class QThread;
@ -45,7 +46,7 @@ public:
void write(qint16 sample); void write(qint16 sample);
bool isRTPCapable() const { return false; } bool isRTPCapable() const;
bool selectType(SinkType type); bool selectType(SinkType type);
void moveToThread(QThread *thread); void moveToThread(QThread *thread);
@ -54,8 +55,12 @@ public:
protected: protected:
SinkType m_type; SinkType m_type;
UDPSink<qint16> *m_udpBufferAudioMono; QUdpSocket *m_udpSocket;
RTPSink *m_rtpBufferAudio; RTPSink *m_rtpBufferAudio;
char m_data[65536];
unsigned int m_bufferIndex;
QHostAddress m_address;
unsigned int m_port;
}; };

View File

@ -19,19 +19,20 @@
#include "dsp/dsptypes.h" #include "dsp/dsptypes.h"
#include <algorithm> #include <algorithm>
RTPSink::RTPSink(const QString& address, uint16_t port, PayloadType payloadType) : RTPSink::RTPSink(QUdpSocket *udpSocket, bool stereo) :
m_payloadType(payloadType), m_payloadType(stereo ? RTPSink::PayloadL16Stereo : RTPSink::PayloadL16Mono),
m_sampleRate(48000), m_sampleRate(48000),
m_sampleBytes(0), m_sampleBytes(0),
m_packetSamples(0), m_packetSamples(0),
m_bufferSize(0), m_bufferSize(0),
m_sampleBufferIndex(0), m_sampleBufferIndex(0),
m_byteBuffer(0), m_byteBuffer(0),
m_destport(port), m_destport(9998),
m_mutex(QMutex::Recursive) m_mutex(QMutex::Recursive)
{ {
m_rtpSessionParams.SetOwnTimestampUnit(1.0 / (double) m_sampleRate); m_rtpSessionParams.SetOwnTimestampUnit(1.0 / (double) m_sampleRate);
m_rtpTransmissionParams.SetRTCPMultiplexing(true); // do not allocate another socket for RTCP m_rtpTransmissionParams.SetRTCPMultiplexing(true); // do not allocate another socket for RTCP
m_rtpTransmissionParams.SetUseExistingSockets(udpSocket, udpSocket);
int status = m_rtpTransmitter.Init(); int status = m_rtpTransmitter.Init();
if (status < 0) { if (status < 0) {
@ -52,14 +53,12 @@ RTPSink::RTPSink(const QString& address, uint16_t port, PayloadType payloadType)
qDebug("RTPSink::RTPSink: created session: %s", qrtplib::RTPGetErrorString(status).c_str()); qDebug("RTPSink::RTPSink: created session: %s", qrtplib::RTPGetErrorString(status).c_str());
} }
setPayloadType(payloadType); setPayloadType(m_payloadType);
m_valid = true; m_valid = true;
uint32_t endianTest32 = 1; uint32_t endianTest32 = 1;
uint8_t *ptr = (uint8_t*) &endianTest32; uint8_t *ptr = (uint8_t*) &endianTest32;
m_endianReverse = (*ptr == 1); m_endianReverse = (*ptr == 1);
m_destip.setAddress(address);
} }
RTPSink::~RTPSink() RTPSink::~RTPSink()

View File

@ -33,6 +33,8 @@
#include "util/export.h" #include "util/export.h"
class QUdpSocket;
class RTPSink class RTPSink
{ {
public: public:
@ -42,7 +44,7 @@ public:
PayloadL16Stereo, PayloadL16Stereo,
} PayloadType; } PayloadType;
RTPSink(const QString& address, uint16_t port, PayloadType payloadType = PayloadL16Mono); RTPSink(QUdpSocket *udpSocket, bool stereo);
~RTPSink(); ~RTPSink();
bool isValid() const { return m_valid; } bool isValid() const { return m_valid; }
@ -55,10 +57,6 @@ public:
void write(const uint8_t *sampleByte); void write(const uint8_t *sampleByte);
void write(const uint8_t *sampleByte, int nbSamples); void write(const uint8_t *sampleByte, int nbSamples);
void moveToThread(QThread *thread) {
m_rtpTransmitter.moveToThread(thread);
}
protected: protected:
/** Reverse endianess in destination buffer */ /** Reverse endianess in destination buffer */
static void writeNetBuf(uint8_t *dest, const uint8_t *src, unsigned int elemLen, unsigned int bytesLen, bool endianReverse); static void writeNetBuf(uint8_t *dest, const uint8_t *src, unsigned int elemLen, unsigned int bytesLen, bool endianReverse);