diff --git a/qrtplib/rtpudptransmitter.cpp b/qrtplib/rtpudptransmitter.cpp index cc2ee3a3e..957f62ec2 100644 --- a/qrtplib/rtpudptransmitter.cpp +++ b/qrtplib/rtpudptransmitter.cpp @@ -48,6 +48,7 @@ RTPUDPTransmitter::RTPUDPTransmitter() : m_init = false; m_rtcpsock = 0; m_rtpsock = 0; + m_deletesocketswhendone = false; m_waitingfordata = false; m_rtcpPort = 0; m_rtpPort = 0; @@ -122,15 +123,24 @@ int RTPUDPTransmitter::Create(std::size_t maximumpacketsize, const RTPTransmissi } } - 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()) + if (params->GetUseExistingSockets(&m_rtpsock, &m_rtcpsock)) { - m_rtcpsock = m_rtpsock; - m_rtcpPort = m_rtpPort; - } else { - m_rtcpsock = new QUdpSocket(); + m_deletesocketswhendone = false; + } + else + { + 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 @@ -174,17 +184,6 @@ int RTPUDPTransmitter::BindSockets() 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() { if (!m_init) { @@ -196,11 +195,14 @@ void RTPUDPTransmitter::Destroy() return; } - if (m_rtpsock != m_rtcpsock) { - delete m_rtcpsock; - } + if (m_deletesocketswhendone) + { + if (m_rtpsock != m_rtcpsock) { + delete m_rtcpsock; + } - delete m_rtpsock; + delete m_rtpsock; + } m_created = false; } diff --git a/qrtplib/rtpudptransmitter.h b/qrtplib/rtpudptransmitter.h index add4561ee..223810a58 100644 --- a/qrtplib/rtpudptransmitter.h +++ b/qrtplib/rtpudptransmitter.h @@ -142,6 +142,16 @@ public: 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. */ int GetRTPSendBufferSize() const { @@ -184,6 +194,20 @@ public: 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: QHostAddress m_bindAddress; QNetworkInterface m_mcastInterface; @@ -195,6 +219,7 @@ private: uint16_t m_forcedrtcpport; QUdpSocket *m_rtpsock, *m_rtcpsock; + bool m_useexistingsockets; }; inline RTPUDPTransmissionParams::RTPUDPTransmissionParams() : @@ -210,6 +235,7 @@ inline RTPUDPTransmissionParams::RTPUDPTransmissionParams() : m_forcedrtcpport = 0; m_rtpsock = 0; m_rtcpsock = 0; + m_useexistingsockets = false; } /** Additional information about the UDP over IPv4 transmitter. */ @@ -321,6 +347,7 @@ private: bool m_created; bool m_waitingfordata; QUdpSocket *m_rtpsock, *m_rtcpsock; + bool m_deletesocketswhendone; QHostAddress m_localIP; //!< from parameters bind IP QNetworkInterface m_multicastInterface; //!< from parameters multicast interface uint16_t m_rtpPort, m_rtcpPort; diff --git a/sdrbase/audio/audionetsink.cpp b/sdrbase/audio/audionetsink.cpp index e2f982b5c..85ee786ac 100644 --- a/sdrbase/audio/audionetsink.cpp +++ b/sdrbase/audio/audionetsink.cpp @@ -16,34 +16,36 @@ /////////////////////////////////////////////////////////////////////////////////// #include "audionetsink.h" -#include "util/udpsink.h" #include "util/rtpsink.h" +#include +#include + const int AudioNetSink::m_udpBlockSize = 512; AudioNetSink::AudioNetSink(QObject *parent, bool stereo) : m_type(SinkUDP), - m_udpBufferAudioMono(0), - m_rtpBufferAudio(0) + m_rtpBufferAudio(0), + m_bufferIndex(0), + m_port(9998) { - m_udpBufferAudioMono = new UDPSink(parent, m_udpBlockSize); - //m_rtpBufferAudio = new RTPSink("127.0.0.1", 9999, stereo ? RTPSink::PayloadL16Stereo : RTPSink::PayloadL16Mono); + m_udpSocket = new QUdpSocket(parent); + m_rtpBufferAudio = new RTPSink(m_udpSocket, stereo); } AudioNetSink::~AudioNetSink() { - if (m_udpBufferAudioMono) { - delete m_udpBufferAudioMono; - } if (m_rtpBufferAudio) { delete m_rtpBufferAudio; } + + m_udpSocket->deleteLater(); // this thread is not the owner thread (was moved) } -//bool AudioNetSink::isRTPCapable() const -//{ -// return m_rtpBufferAudio->isValid(); -//} +bool AudioNetSink::isRTPCapable() const +{ + return m_rtpBufferAudio->isValid(); +} bool AudioNetSink::selectType(SinkType type) { @@ -65,9 +67,9 @@ bool AudioNetSink::selectType(SinkType type) void AudioNetSink::setDestination(const QString& address, uint16_t port) { - if (m_udpBufferAudioMono) { - m_udpBufferAudioMono->setDestination(address, port); - } + m_address.setAddress(const_cast(address)); + m_port = port; + if (m_rtpBufferAudio) { m_rtpBufferAudio->setDestination(address, port); } @@ -89,21 +91,28 @@ void AudioNetSink::deleteDestination(const QString& address, uint16_t port) void AudioNetSink::write(qint16 sample) { - if (m_type == SinkUDP) { - m_udpBufferAudioMono->write(sample); - } else if (m_type == SinkRTP) { + if (m_type == SinkUDP) + { + 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); } } void AudioNetSink::moveToThread(QThread *thread) { - if (m_udpBufferAudioMono) { - m_udpBufferAudioMono->moveToThread(thread); - } - - if (m_rtpBufferAudio) { - m_rtpBufferAudio->moveToThread(thread); - } + m_udpSocket->moveToThread(thread); } diff --git a/sdrbase/audio/audionetsink.h b/sdrbase/audio/audionetsink.h index 9a8c9ca2b..e0e08dfc7 100644 --- a/sdrbase/audio/audionetsink.h +++ b/sdrbase/audio/audionetsink.h @@ -21,10 +21,11 @@ #include "dsp/dsptypes.h" #include "util/export.h" -#include #include +#include +#include -template class UDPSink; +class QUdpSocket; class RTPSink; class QThread; @@ -45,7 +46,7 @@ public: void write(qint16 sample); - bool isRTPCapable() const { return false; } + bool isRTPCapable() const; bool selectType(SinkType type); void moveToThread(QThread *thread); @@ -54,8 +55,12 @@ public: protected: SinkType m_type; - UDPSink *m_udpBufferAudioMono; + QUdpSocket *m_udpSocket; RTPSink *m_rtpBufferAudio; + char m_data[65536]; + unsigned int m_bufferIndex; + QHostAddress m_address; + unsigned int m_port; }; diff --git a/sdrbase/util/rtpsink.cpp b/sdrbase/util/rtpsink.cpp index 76cba88d8..67232eb4e 100644 --- a/sdrbase/util/rtpsink.cpp +++ b/sdrbase/util/rtpsink.cpp @@ -19,19 +19,20 @@ #include "dsp/dsptypes.h" #include -RTPSink::RTPSink(const QString& address, uint16_t port, PayloadType payloadType) : - m_payloadType(payloadType), +RTPSink::RTPSink(QUdpSocket *udpSocket, bool stereo) : + m_payloadType(stereo ? RTPSink::PayloadL16Stereo : RTPSink::PayloadL16Mono), m_sampleRate(48000), m_sampleBytes(0), m_packetSamples(0), m_bufferSize(0), m_sampleBufferIndex(0), m_byteBuffer(0), - m_destport(port), + m_destport(9998), m_mutex(QMutex::Recursive) { m_rtpSessionParams.SetOwnTimestampUnit(1.0 / (double) m_sampleRate); m_rtpTransmissionParams.SetRTCPMultiplexing(true); // do not allocate another socket for RTCP + m_rtpTransmissionParams.SetUseExistingSockets(udpSocket, udpSocket); int status = m_rtpTransmitter.Init(); 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()); } - setPayloadType(payloadType); + setPayloadType(m_payloadType); m_valid = true; uint32_t endianTest32 = 1; uint8_t *ptr = (uint8_t*) &endianTest32; m_endianReverse = (*ptr == 1); - - m_destip.setAddress(address); } RTPSink::~RTPSink() diff --git a/sdrbase/util/rtpsink.h b/sdrbase/util/rtpsink.h index 051316d65..0c4666a88 100644 --- a/sdrbase/util/rtpsink.h +++ b/sdrbase/util/rtpsink.h @@ -33,6 +33,8 @@ #include "util/export.h" +class QUdpSocket; + class RTPSink { public: @@ -42,7 +44,7 @@ public: PayloadL16Stereo, } PayloadType; - RTPSink(const QString& address, uint16_t port, PayloadType payloadType = PayloadL16Mono); + RTPSink(QUdpSocket *udpSocket, bool stereo); ~RTPSink(); bool isValid() const { return m_valid; } @@ -55,10 +57,6 @@ public: void write(const uint8_t *sampleByte); void write(const uint8_t *sampleByte, int nbSamples); - void moveToThread(QThread *thread) { - m_rtpTransmitter.moveToThread(thread); - } - protected: /** Reverse endianess in destination buffer */ static void writeNetBuf(uint8_t *dest, const uint8_t *src, unsigned int elemLen, unsigned int bytesLen, bool endianReverse);