qrtplib: new RTPUDPTransmitter

This commit is contained in:
f4exb 2018-03-05 01:17:19 +01:00
parent 503c6093b9
commit afe3fbabd3
14 changed files with 835 additions and 734 deletions

View File

@ -42,6 +42,7 @@ set (qrtplib_HEADERS
rtptransmitter.h
rtptypes_win.h
rtptypes.h
rtpudpransmitter.h
# rtpudpv4transmitter.h
# rtpudpv4transmitternobind.h
# rtpexternaltransmitter.h
@ -82,6 +83,7 @@ set(qrtplib_SOURCES
rtpsourcedata.cpp
rtpsources.cpp
rtptimeutilities.cpp
rtpudptransmitter.cpp
# rtpudpv4transmitter.cpp
# rtpudpv4transmitternobind.cpp
# rtpexternaltransmitter.cpp

View File

@ -61,30 +61,30 @@ RTCPCompoundPacket::RTCPCompoundPacket(RTPRawPacket &rawpack)
std::size_t datalen = rawpack.GetDataLength();
error = ParseData(data, datalen);
if (error < 0)
if (error < 0) {
return;
}
compoundpacket = rawpack.GetData();
compoundpacketlength = rawpack.GetDataLength();
deletepacket = true;
rawpack.ZeroData();
rtcppackit = rtcppacklist.begin();
}
RTCPCompoundPacket::RTCPCompoundPacket(uint8_t *packet, std::size_t packetlen, bool deletedata)
RTCPCompoundPacket::RTCPCompoundPacket(uint8_t *packet, std::size_t packetlen)
{
compoundpacket = 0;
compoundpacketlength = 0;
error = ParseData(packet, packetlen);
if (error < 0)
if (error < 0) {
return;
}
compoundpacket = packet;
compoundpacketlength = packetlen;
deletepacket = deletedata;
rtcppackit = rtcppacklist.begin();
}
@ -94,7 +94,6 @@ RTCPCompoundPacket::RTCPCompoundPacket()
compoundpacket = 0;
compoundpacketlength = 0;
error = 0;
deletepacket = true;
}
int RTCPCompoundPacket::ParseData(uint8_t *data, std::size_t datalen)
@ -195,16 +194,16 @@ int RTCPCompoundPacket::ParseData(uint8_t *data, std::size_t datalen)
RTCPCompoundPacket::~RTCPCompoundPacket()
{
ClearPacketList();
if (compoundpacket && deletepacket)
delete[] compoundpacket;
}
void RTCPCompoundPacket::ClearPacketList()
{
std::list<RTCPPacket *>::const_iterator it;
for (it = rtcppacklist.begin(); it != rtcppacklist.end(); it++)
for (it = rtcppacklist.begin(); it != rtcppacklist.end(); it++) {
delete *it;
}
rtcppacklist.clear();
rtcppackit = rtcppacklist.begin();
}

View File

@ -58,12 +58,8 @@ public:
/** Creates an RTCPCompoundPacket instance from the data in \c rawpack, installing a memory manager if specified. */
RTCPCompoundPacket(RTPRawPacket &rawpack);
/** Creates an RTCPCompoundPacket instance from the data in \c packet}, with size \c len.
* Creates an RTCPCompoundPacket instance from the data in \c packet}, with size \c len. The \c deletedata
* flag specifies if the data in \c packet should be deleted when the compound packet is destroyed. If
* specified, a memory manager will be installed.
*/
RTCPCompoundPacket(uint8_t *packet, std::size_t len, bool deletedata = true);
/** Creates an RTCPCompoundPacket instance from the data in \c packet}, with size \c len. */
RTCPCompoundPacket(uint8_t *packet, std::size_t len);
protected:
RTCPCompoundPacket(); // this is for the compoundpacket builder
public:
@ -118,7 +114,6 @@ protected:
uint8_t *compoundpacket;
std::size_t compoundpacketlength;
bool deletepacket;
std::list<RTCPPacket *> rtcppacklist;
std::list<RTCPPacket *>::const_iterator rtcppackit;

View File

@ -77,4 +77,9 @@ bool RTPAddress::IsFromSameHost(const RTPAddress *addr) const
return addr->address == address;
}
bool RTPAddress::operator==(const RTPAddress& otherAddress)
{
return IsSameAddress(&otherAddress);
}
} // namespace

View File

@ -82,6 +82,9 @@ public:
*/
bool IsFromSameHost(const RTPAddress *addr) const;
/** Equality */
bool operator==(const RTPAddress& otherAddress);
/** Get host address */
const QHostAddress& getAddress() const
{

View File

@ -7,7 +7,7 @@
This library was developed at the Expertise Centre for Digital Media
(http://www.edm.uhasselt.be), a research center of the Hasselt University
(http://www.uhasselt.be). The library is based upon work done for
(http://www.uhasselt.be). The library is based upon work done for
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
@ -47,13 +47,7 @@
#else
#include <stdio.h>
#define RTP_SNPRINTF snprintf
#endif
#ifdef RTP_HAVE_STRNCPY_S
#define RTP_STRNCPY(dest, src, len) strncpy_s((dest), (len), (src), _TRUNCATE)
#else
#define RTP_STRNCPY(dest, src, len) strncpy((dest), (src), (len))
#endif // RTP_HAVE_STRNCPY_S
#endif
#endif // RTPINTERNALUTILS_H

View File

@ -67,18 +67,59 @@ RTPPacket::RTPPacket(RTPRawPacket &rawpack) :
error = ParseRawPacket(rawpack);
}
RTPPacket::RTPPacket(uint8_t payloadtype, const void *payloaddata, std::size_t payloadlen, uint16_t seqnr, uint32_t timestamp, uint32_t ssrc, bool gotmarker, uint8_t numcsrcs,
const uint32_t *csrcs, bool gotextension, uint16_t extensionid, uint16_t extensionlen_numwords, const void *extensiondata, std::size_t maxpacksize) :
receivetime(0, 0)
RTPPacket::RTPPacket(
uint8_t payloadtype,
const void *payloaddata,
std::size_t payloadlen,
uint16_t seqnr,
uint32_t timestamp,
uint32_t ssrc,
bool gotmarker,
uint8_t numcsrcs,
const uint32_t *csrcs,
bool gotextension,
uint16_t extensionid,
uint16_t extensionlen_numwords,
const void *extensiondata,
std::size_t maxpacksize) :
receivetime(0, 0)
{
Clear();
error = BuildPacket(payloadtype, payloaddata, payloadlen, seqnr, timestamp, ssrc, gotmarker, numcsrcs, csrcs, gotextension, extensionid, extensionlen_numwords, extensiondata,
0, maxpacksize);
error = BuildPacket(
payloadtype,
payloaddata,
payloadlen,
seqnr,
timestamp,
ssrc,
gotmarker,
numcsrcs,
csrcs,
gotextension,
extensionid,
extensionlen_numwords,
extensiondata,
0,
maxpacksize);
}
RTPPacket::RTPPacket(uint8_t payloadtype, const void *payloaddata, std::size_t payloadlen, uint16_t seqnr, uint32_t timestamp, uint32_t ssrc, bool gotmarker, uint8_t numcsrcs,
const uint32_t *csrcs, bool gotextension, uint16_t extensionid, uint16_t extensionlen_numwords, const void *extensiondata, void *buffer, std::size_t buffersize) :
receivetime(0, 0)
RTPPacket::RTPPacket(
uint8_t payloadtype,
const void *payloaddata,
std::size_t payloadlen,
uint16_t seqnr,
uint32_t timestamp,
uint32_t ssrc,
bool gotmarker,
uint8_t numcsrcs,
const uint32_t *csrcs,
bool gotextension,
uint16_t extensionid,
uint16_t extensionlen_numwords,
const void *extensiondata,
void *buffer,
std::size_t buffersize) :
receivetime(0, 0)
{
Clear();
if (buffer == 0)
@ -86,8 +127,22 @@ RTPPacket::RTPPacket(uint8_t payloadtype, const void *payloaddata, std::size_t p
else if (buffersize <= 0)
error = ERR_RTP_PACKET_ILLEGALBUFFERSIZE;
else
error = BuildPacket(payloadtype, payloaddata, payloadlen, seqnr, timestamp, ssrc, gotmarker, numcsrcs, csrcs, gotextension, extensionid, extensionlen_numwords,
extensiondata, buffer, buffersize);
error = BuildPacket(
payloadtype,
payloaddata,
payloadlen,
seqnr,
timestamp,
ssrc,
gotmarker,
numcsrcs,
csrcs,
gotextension,
extensionid,
extensionlen_numwords,
extensiondata,
buffer,
buffersize);
}
int RTPPacket::ParseRawPacket(RTPRawPacket &rawpack)
@ -188,9 +243,6 @@ int RTPPacket::ParseRawPacket(RTPRawPacket &rawpack)
RTPPacket::packetlength = packetlen;
RTPPacket::payloadlength = payloadlength;
// We'll zero the data of the raw packet, since we're using it here now!
rawpack.ZeroData();
return 0;
}
@ -209,8 +261,22 @@ uint32_t RTPPacket::GetCSRC(int num) const
return csrcval_hbo;
}
int RTPPacket::BuildPacket(uint8_t payloadtype, const void *payloaddata, std::size_t payloadlen, uint16_t seqnr, uint32_t timestamp, uint32_t ssrc, bool gotmarker, uint8_t numcsrcs,
const uint32_t *csrcs, bool gotextension, uint16_t extensionid, uint16_t extensionlen_numwords, const void *extensiondata, void *buffer, std::size_t maxsize)
int RTPPacket::BuildPacket(
uint8_t payloadtype,
const void *payloaddata,
std::size_t payloadlen,
uint16_t seqnr,
uint32_t timestamp,
uint32_t ssrc,
bool gotmarker,
uint8_t numcsrcs,
const uint32_t *csrcs,
bool gotextension,
uint16_t extensionid,
uint16_t extensionlen_numwords,
const void *extensiondata,
void *buffer,
std::size_t maxsize)
{
if (numcsrcs > RTP_MAXCSRCS)
return ERR_RTP_PACKET_TOOMANYCSRCS;

View File

@ -57,7 +57,7 @@ public:
* The flag which indicates whether this data is RTP or RTCP data is set to \c rtp. A memory
* manager can be installed as well.
*/
RTPRawPacket(uint8_t *data, std::size_t datalen, RTPAddress *address, RTPTime &recvtime, bool rtp);
RTPRawPacket(const uint8_t *data, std::size_t datalen, const RTPAddress& address, RTPTime &recvtime, bool rtp);
~RTPRawPacket();
/** Returns the pointer to the data which is contained in this packet. */
@ -79,7 +79,7 @@ public:
}
/** Returns the address stored in this packet. */
const RTPAddress *GetSenderAddress() const
const RTPAddress& GetSenderAddress() const
{
return senderaddress;
}
@ -90,45 +90,28 @@ public:
return isrtp;
}
/** Sets the pointer to the data stored in this packet to zero.
* Sets the pointer to the data stored in this packet to zero. This will prevent
* a \c delete call for the actual data when the destructor of RTPRawPacket is called.
* This function is used by the RTPPacket and RTCPCompoundPacket classes to obtain
* the packet data (without having to copy it) and to make sure the data isn't deleted
* when the destructor of RTPRawPacket is called.
*/
void ZeroData()
{
packetdata = 0;
packetdatalength = 0;
}
/** Allocates a number of bytes for RTP or RTCP data using the memory manager that
* was used for this raw packet instance, can be useful if the RTPRawPacket::SetData
* function will be used. */
uint8_t *AllocateBytes(int recvlen) const;
/** Deallocates the previously stored data and replaces it with the data that's
* specified, can be useful when e.g. decrypting data in RTPSession::OnChangeIncomingData */
void SetData(uint8_t *data, std::size_t datalen);
void SetData(const uint8_t *data, std::size_t datalen);
/** Deallocates the currently stored RTPAddress instance and replaces it
* with the one that's specified (you probably don't need this function). */
void SetSenderAddress(RTPAddress *address);
void SetSenderAddress(const RTPAddress& address);
private:
void DeleteData();
uint8_t *packetdata;
std::size_t packetdatalength;
RTPTime receivetime;
RTPAddress *senderaddress;
RTPAddress senderaddress;
bool isrtp;
};
inline RTPRawPacket::RTPRawPacket(uint8_t *data, std::size_t datalen, RTPAddress *address, RTPTime &recvtime, bool rtp) :
inline RTPRawPacket::RTPRawPacket(const uint8_t *data, std::size_t datalen, const RTPAddress& address, RTPTime &recvtime, bool rtp) :
receivetime(recvtime)
{
packetdata = data;
packetdata = new uint8_t[datalen];
memcpy(packetdata, data, datalen);
packetdatalength = datalen;
senderaddress = address;
isrtp = rtp;
@ -142,33 +125,25 @@ inline RTPRawPacket::~RTPRawPacket()
inline void RTPRawPacket::DeleteData()
{
if (packetdata)
{
delete[] packetdata;
if (senderaddress)
delete senderaddress;
packetdata = 0;
senderaddress = 0;
packetdata = 0;
}
}
inline uint8_t *RTPRawPacket::AllocateBytes(int recvlen) const
inline void RTPRawPacket::SetData(const uint8_t *data, std::size_t datalen)
{
return new uint8_t[recvlen];
}
inline void RTPRawPacket::SetData(uint8_t *data, std::size_t datalen)
{
if (packetdata)
if (packetdata) {
delete[] packetdata;
}
packetdata = data;
packetdata = new uint8_t[datalen];
memcpy(packetdata, data, datalen);
packetdatalength = datalen;
}
inline void RTPRawPacket::SetSenderAddress(RTPAddress *address)
inline void RTPRawPacket::SetSenderAddress(const RTPAddress& address)
{
if (senderaddress)
delete senderaddress;
senderaddress = address;
}

File diff suppressed because it is too large Load Diff

View File

@ -140,9 +140,6 @@ public:
/** Leaves the multicast group specified by \c addr. */
int LeaveMulticastGroup(const RTPAddress &addr);
/** Leaves all multicast groups. */
void LeaveAllMulticastGroups();
/** Sends the RTP packet with payload \c data which has length \c len.
* Sends the RTP packet with payload \c data which has length \c len.
* The used payload type, marker and timestamp increment will be those that have been set
@ -233,23 +230,6 @@ public:
/** Frees the memory used by the transmission information \c inf. */
void DeleteTransmissionInfo(RTPTransmissionInfo *inf);
/** If you're not using the poll thread, this function must be called regularly to process incoming data
* and to send RTCP data when necessary.
*/
int Poll();
/** Waits at most a time \c delay until incoming data has been detected.
* Waits at most a time \c delay until incoming data has been detected. Only works when you're not
* using the poll thread. If \c dataavailable is not \c NULL, it should be set to \c true if data
* was actually read and to \c false otherwise.
*/
int WaitForIncomingData(const RTPTime &delay, bool *dataavailable = 0);
/** If the previous function has been called, this one aborts the waiting (only works when you're not
* using the poll thread).
*/
int AbortWait();
/** Returns the time interval after which an RTCP compound packet may have to be sent (only works when
* you're not using the poll thread.
*/
@ -574,7 +554,7 @@ private:
RTPTransmitter *rtptrans;
bool created;
bool deletetransmitter;
bool usingpollthread, needthreadsafety;
bool usingpollthread;
bool acceptownpackets;
bool useSR_BYEifpossible;
std::size_t maxpacksize;

View File

@ -191,7 +191,7 @@ int RTPSources::ProcessRawPacket(RTPRawPacket *rawpack, RTPTransmitter *rtptrans
bool stored = false;
bool ownpacket = false;
int i;
const RTPAddress *senderaddress = rawpack->GetSenderAddress();
const RTPAddress& senderaddress = rawpack->GetSenderAddress();
for (i = 0; !ownpacket && i < numtrans; i++)
{
@ -217,7 +217,7 @@ int RTPSources::ProcessRawPacket(RTPRawPacket *rawpack, RTPTransmitter *rtptrans
}
else
{
if ((status = ProcessRTPPacket(rtppack, rawpack->GetReceiveTime(), senderaddress, &stored)) < 0)
if ((status = ProcessRTPPacket(rtppack, rawpack->GetReceiveTime(), &senderaddress, &stored)) < 0)
{
if (!stored)
delete rtppack;
@ -245,7 +245,7 @@ int RTPSources::ProcessRawPacket(RTPRawPacket *rawpack, RTPTransmitter *rtptrans
{
bool ownpacket = false;
int i;
const RTPAddress *senderaddress = rawpack->GetSenderAddress();
const RTPAddress& senderaddress = rawpack->GetSenderAddress();
for (i = 0; !ownpacket && i < numtrans; i++)
{
@ -266,7 +266,7 @@ int RTPSources::ProcessRawPacket(RTPRawPacket *rawpack, RTPTransmitter *rtptrans
}
else // not our own packet
{
status = ProcessRTCPCompoundPacket(&rtcpcomppack, rawpack->GetReceiveTime(), rawpack->GetSenderAddress());
status = ProcessRTCPCompoundPacket(&rtcpcomppack, rawpack->GetReceiveTime(), &rawpack->GetSenderAddress());
if (status < 0)
return status;
}

View File

@ -94,11 +94,8 @@ public:
{
}
/** This function must be called before the transmission component can be used.
* This function must be called before the transmission component can be used. Depending on
* the value of \c threadsafe, the component will be created for thread-safe usage or not.
*/
virtual int Init(bool threadsafe) = 0;
/** This function must be called before the transmission component can be used. */
virtual int Init() = 0;
/** Prepares the component to be used.
* Prepares the component to be used. The parameter \c maxpacksize specifies the maximum size
@ -110,6 +107,9 @@ public:
*/
virtual int Create(std::size_t maxpacksize, const RTPTransmissionParams *transparams) = 0;
/** Bind the RTP and RTCP sockets to ports that were set at creation time */
virtual int BindSockets() = 0;
/** By calling this function, buffers are cleared and the component cannot be used anymore.
* By calling this function, buffers are cleared and the component cannot be used anymore.
* Only when the Create function is called again can the component be used again. */
@ -129,36 +129,13 @@ public:
*/
virtual void DeleteTransmissionInfo(RTPTransmissionInfo *inf) = 0;
/** Looks up the local host name.
* Looks up the local host name based upon internal information about the local host's
* addresses. This function might take some time since a DNS query might be done. \c bufferlength
* should initially contain the number of bytes that may be stored in \c buffer. If the function
* succeeds, \c bufferlength is set to the number of bytes stored in \c buffer. Note that the data
* in \c buffer is not NULL-terminated. If the function fails because the buffer isn't large enough,
* it returns \c ERR_RTP_TRANS_BUFFERLENGTHTOOSMALL and stores the number of bytes needed in
* \c bufferlength.
*/
virtual int GetLocalHostName(uint8_t *buffer, std::size_t *bufferlength) = 0;
/** Returns \c true if the address specified by \c addr is one of the addresses of the transmitter. */
virtual bool ComesFromThisTransmitter(const RTPAddress *addr) = 0;
virtual bool ComesFromThisTransmitter(const RTPAddress& addr) = 0;
/** Returns the amount of bytes that will be added to the RTP packet by the underlying layers (excluding
* the link layer). */
virtual std::size_t GetHeaderOverhead() = 0;
/** Checks for incoming data and stores it. */
virtual int Poll() = 0;
/** Waits until incoming data is detected.
* Waits at most a time \c delay until incoming data has been detected. If \c dataavailable is not NULL,
* it should be set to \c true if data was actually read and to \c false otherwise.
*/
virtual int WaitForIncomingData(const RTPTime &delay, bool *dataavailable = 0) = 0;
/** If the previous function has been called, this one aborts the waiting. */
virtual int AbortWait() = 0;
/** Send a packet with length \c len containing \c data to all RTP addresses of the current destination list. */
virtual int SendRTPData(const void *data, std::size_t len) = 0;
@ -183,9 +160,6 @@ public:
/** Leaves the multicast group specified by \c addr. */
virtual int LeaveMulticastGroup(const RTPAddress &addr) = 0;
/** Leaves all the multicast groups that have been joined. */
virtual void LeaveAllMulticastGroups() = 0;
/** Sets the receive mode.
* Sets the receive mode to \c m, which is one of the following: RTPTransmitter::AcceptAll,
* RTPTransmitter::AcceptSome or RTPTransmitter::IgnoreSome. Note that if the receive
@ -214,10 +188,7 @@ public:
/** Sets the maximum packet size which the transmitter should allow to \c s. */
virtual int SetMaximumPacketSize(std::size_t s) = 0;
/** Returns \c true if packets can be obtained using the GetNextPacket member function. */
virtual bool NewDataAvailable() = 0;
/** Returns the raw data of a received RTP packet (received during the Poll function)
/** Returns the raw data of a received RTP packet
* in an RTPRawPacket instance. */
virtual RTPRawPacket *GetNextPacket() = 0;
};

View File

@ -32,13 +32,17 @@
#include "rtpudptransmitter.h"
#include "rtperrors.h"
#include "rtpaddress.h"
#include "rtpstructs.h"
#include "rtprawpacket.h"
#define RTPUDPTRANS_MAXPACKSIZE 65535
#include <QUdpSocket>
namespace qrtplib
{
RTPUDPTransmitter::RTPUDPTransmitter()
RTPUDPTransmitter::RTPUDPTransmitter() :
m_rawPacketQueueLock(QMutex::Recursive)
{
m_created = false;
m_init = false;
@ -48,9 +52,7 @@ RTPUDPTransmitter::RTPUDPTransmitter()
m_closesocketswhendone = false;
m_rtcpPort = 0;
m_rtpPort = 0;
m_supportsmulticasting = false;
m_receivemode = RTPTransmitter::AcceptAll;
m_localhostname = 0;
}
RTPUDPTransmitter::~RTPUDPTransmitter()
@ -71,11 +73,9 @@ int RTPUDPTransmitter::Init()
int RTPUDPTransmitter::Create(std::size_t maximumpacketsize, const RTPTransmissionParams *transparams)
{
const RTPUDPTransmissionParams *params, defaultparams;
struct sockaddr_in addr;
qint64 size;
int status;
if (maximumpacketsize > RTPUDPTRANS_MAXPACKSIZE) {
if (maximumpacketsize > m_absoluteMaxPackSize) {
return ERR_RTP_UDPV4TRANS_SPECIFIEDSIZETOOBIG;
}
@ -98,7 +98,7 @@ int RTPUDPTransmitter::Create(std::size_t maximumpacketsize, const RTPTransmissi
{
return ERR_RTP_UDPV4TRANS_ILLEGALPARAMETERS;
}
params = (const RTPUDPv4TransmissionParams *) transparams;
params = (const RTPUDPTransmissionParams *) transparams;
}
// Determine the port numbers
@ -155,18 +155,35 @@ int RTPUDPTransmitter::Create(std::size_t maximumpacketsize, const RTPTransmissi
}
m_maxpacksize = maximumpacketsize;
m_mcastifaceIP = params->GetMulticastInterfaceIP();
m_multicastInterface = params->GetMulticastInterface();
m_receivemode = RTPTransmitter::AcceptAll;
m_localhostname = 0;
m_localhostnamelength = 0;
m_waitingfordata = false;
m_created = true;
return 0;
}
int RTPUDPTransmitter::BindSockets()
{
if (!m_rtpsock->bind(m_localIP, m_rtpPort)) {
return ERR_RTP_UDPV4TRANS_CANTBINDRTPSOCKET;
}
connect(m_rtpsock, SIGNAL(readyRead()), this, SLOT(readRTPPendingDatagrams()));
if (m_rtpsock != m_rtcpsock)
{
if (!m_rtcpsock->bind(m_localIP, m_rtcpPort)) {
return ERR_RTP_UDPV4TRANS_CANTBINDRTCPSOCKET;
}
connect(m_rtcpsock, SIGNAL(readyRead()), this, SLOT(readRTCPPendingDatagrams()));
}
return 0;
}
void RTPUDPTransmitter::Destroy()
{
if (!m_init) {
@ -178,16 +195,6 @@ void RTPUDPTransmitter::Destroy()
return;
}
if (m_localhostname)
{
delete[] m_localhostname;
m_localhostname = 0;
m_localhostnamelength = 0;
}
FlushPackets();
ClearAcceptIgnoreInfo();
if (m_closesocketswhendone)
{
if (m_rtpsock != m_rtcpsock) {
@ -206,8 +213,7 @@ RTPTransmissionInfo *RTPUDPTransmitter::GetTransmissionInfo()
return 0;
}
RTPTransmissionInfo *tinf = new RTPUDPv4TransmissionNoBindInfo(
m_localIP, m_rtpsock, m_rtcpsock, m_rtpPort, m_rtcpPort);
RTPTransmissionInfo *tinf = new RTPUDPTransmissionInfo(m_localIP, m_rtpsock, m_rtcpsock, m_rtpPort, m_rtcpPort);
return tinf;
}
@ -221,13 +227,326 @@ void RTPUDPTransmitter::DeleteTransmissionInfo(RTPTransmissionInfo *inf)
delete inf;
}
bool RTPUDPTransmitter::ComesFromThisTransmitter(const RTPAddress *addr)
bool RTPUDPTransmitter::ComesFromThisTransmitter(const RTPAddress& addr)
{
if (addr->getAddress() != m_localIP) {
if (addr.getAddress() != m_localIP) {
return false;
}
return (addr->getPort() == m_rtpPort) && (addr->getRtcpsendport() == m_rtcpPort);
return (addr.getPort() == m_rtpPort) && (addr.getRtcpsendport() == m_rtcpPort);
}
int RTPUDPTransmitter::SendRTPData(const void *data, std::size_t len)
{
if (!m_init) {
return ERR_RTP_UDPV4TRANS_NOTINIT;
}
if (!m_created) {
return ERR_RTP_UDPV4TRANS_NOTCREATED;
}
if (len > m_maxpacksize)
{
return ERR_RTP_UDPV4TRANS_SPECIFIEDSIZETOOBIG;
}
std::list<RTPAddress>::const_iterator it = m_destinations.begin();
for (; it != m_destinations.end(); ++it)
{
m_rtpsock->writeDatagram((const char*) data, (qint64) len, it->getAddress(), it->getPort());
}
return 0;
}
int RTPUDPTransmitter::SendRTCPData(const void *data, std::size_t len)
{
if (!m_init) {
return ERR_RTP_UDPV4TRANS_NOTINIT;
}
if (!m_created) {
return ERR_RTP_UDPV4TRANS_NOTCREATED;
}
if (len > m_maxpacksize) {
return ERR_RTP_UDPV4TRANS_SPECIFIEDSIZETOOBIG;
}
std::list<RTPAddress>::const_iterator it = m_destinations.begin();
for (; it != m_destinations.end(); ++it)
{
m_rtcpsock->writeDatagram((const char*) data, (qint64) len, it->getAddress(), it->getRtcpsendport());
}
return 0;
}
int RTPUDPTransmitter::AddDestination(const RTPAddress &addr)
{
m_destinations.push_back(addr);
return 0;
}
int RTPUDPTransmitter::DeleteDestination(const RTPAddress &addr)
{
m_destinations.remove(addr);
return 0;
}
void RTPUDPTransmitter::ClearDestinations()
{
m_destinations.clear();
}
bool RTPUDPTransmitter::SupportsMulticasting()
{
QNetworkInterface::InterfaceFlags flags = m_multicastInterface.flags();
QAbstractSocket::SocketState rtpSocketState = m_rtpsock->state();
QAbstractSocket::SocketState rtcpSocketState = m_rtcpsock->state();
return m_multicastInterface.isValid()
&& (rtpSocketState & QAbstractSocket::BoundState)
&& (rtcpSocketState & QAbstractSocket::BoundState)
&& (flags & QNetworkInterface::CanMulticast)
&& (flags & QNetworkInterface::IsRunning)
&& !(flags & QNetworkInterface::IsLoopBack);
}
int RTPUDPTransmitter::JoinMulticastGroup(const RTPAddress &addr)
{
if (!m_init) {
return ERR_RTP_UDPV4TRANS_NOTINIT;
}
if (!m_created) {
return ERR_RTP_UDPV4TRANS_NOTCREATED;
}
if (!SupportsMulticasting()) {
return ERR_RTP_UDPV6TRANS_NOMULTICASTSUPPORT;
}
if (m_rtpsock->joinMulticastGroup(addr.getAddress(), m_multicastInterface))
{
if (m_rtpsock != m_rtcpsock)
{
if (!m_rtcpsock->joinMulticastGroup(addr.getAddress(), m_multicastInterface)) {
return ERR_RTP_UDPV4TRANS_COULDNTJOINMULTICASTGROUP;
}
}
}
else
{
return ERR_RTP_UDPV4TRANS_COULDNTJOINMULTICASTGROUP;
}
return 0;
}
int RTPUDPTransmitter::LeaveMulticastGroup(const RTPAddress &addr)
{
if (!m_init) {
return ERR_RTP_UDPV4TRANS_NOTINIT;
}
if (!m_created) {
return ERR_RTP_UDPV4TRANS_NOTCREATED;
}
if (!SupportsMulticasting()) {
return ERR_RTP_UDPV6TRANS_NOMULTICASTSUPPORT;
}
m_rtpsock->leaveMulticastGroup(addr.getAddress());
if (m_rtpsock != m_rtcpsock)
{
m_rtcpsock->leaveMulticastGroup(addr.getAddress());
}
return 0;
}
int RTPUDPTransmitter::SetReceiveMode(RTPTransmitter::ReceiveMode m)
{
if (!m_init) {
return ERR_RTP_UDPV4TRANS_NOTINIT;
}
if (!m_created) {
return ERR_RTP_UDPV4TRANS_NOTCREATED;
}
if (m != m_receivemode) {
m_receivemode = m;
}
return 0;
}
int RTPUDPTransmitter::AddToIgnoreList(const RTPAddress &addr)
{
m_ignoreList.push_back(addr);
return 0;
}
int RTPUDPTransmitter::DeleteFromIgnoreList(const RTPAddress &addr)
{
m_ignoreList.remove(addr);
return 0;
}
void RTPUDPTransmitter::ClearIgnoreList()
{
m_ignoreList.clear();
}
int RTPUDPTransmitter::AddToAcceptList(const RTPAddress &addr)
{
m_acceptList.push_back(addr);
return 0;
}
int RTPUDPTransmitter::DeleteFromAcceptList(const RTPAddress &addr)
{
m_acceptList.remove(addr);
return 0;
}
void RTPUDPTransmitter::ClearAcceptList()
{
m_acceptList.clear();
}
int RTPUDPTransmitter::SetMaximumPacketSize(std::size_t s)
{
if (!m_init) {
return ERR_RTP_UDPV4TRANS_NOTINIT;
}
if (!m_created) {
return ERR_RTP_UDPV4TRANS_NOTCREATED;
}
if (s > m_absoluteMaxPackSize) {
return ERR_RTP_UDPV4TRANS_SPECIFIEDSIZETOOBIG;
}
m_maxpacksize = s;
return 0;
}
RTPRawPacket *RTPUDPTransmitter::GetNextPacket()
{
QMutexLocker locker(&m_rawPacketQueueLock);
if (m_rawPacketQueue.isEmpty()) {
return 0;
} else {
return m_rawPacketQueue.takeFirst();
}
}
void RTPUDPTransmitter::readRTPPendingDatagrams()
{
while (m_rtpsock->hasPendingDatagrams())
{
RTPTime curtime = RTPTime::CurrentTime();
QHostAddress remoteAddress;
quint16 remotePort;
qint64 pendingDataSize = m_rtpsock->pendingDatagramSize();
qint64 bytesRead = m_rtpsock->readDatagram(m_rtpBuffer, pendingDataSize, &remoteAddress, &remotePort);
qDebug("RTPUDPTransmitter::readRTPPendingDatagrams: %lld bytes read from %s:%d",
bytesRead,
qPrintable(remoteAddress.toString()),
remotePort);
RTPAddress rtpAddress;
rtpAddress.setAddress(remoteAddress);
rtpAddress.setPort(remotePort);
if (ShouldAcceptData(rtpAddress))
{
bool isrtp = true;
if (m_rtpsock == m_rtcpsock) // check payload type when multiplexing
{
if ((std::size_t) bytesRead > sizeof(RTCPCommonHeader))
{
RTCPCommonHeader *rtcpheader = (RTCPCommonHeader *) m_rtpBuffer;
uint8_t packettype = rtcpheader->packettype;
if (packettype >= 200 && packettype <= 204) {
isrtp = false;
}
}
}
RTPRawPacket *pack = new RTPRawPacket((uint8_t *) m_rtpBuffer, bytesRead, rtpAddress, curtime, isrtp);
m_rawPacketQueueLock.lock();
m_rawPacketQueue.append(pack);
m_rawPacketQueueLock.unlock();
emit NewDataAvailable();
}
}
}
void RTPUDPTransmitter::readRTCPPendingDatagrams()
{
while (m_rtcpsock->hasPendingDatagrams())
{
RTPTime curtime = RTPTime::CurrentTime();
QHostAddress remoteAddress;
quint16 remotePort;
qint64 pendingDataSize = m_rtcpsock->pendingDatagramSize();
qint64 bytesRead = m_rtcpsock->readDatagram(m_rtcpBuffer, pendingDataSize, &remoteAddress, &remotePort);
qDebug("RTPUDPTransmitter::readRTCPPendingDatagrams: %lld bytes read from %s:%d",
bytesRead,
qPrintable(remoteAddress.toString()),
remotePort);
RTPAddress rtpAddress;
rtpAddress.setAddress(remoteAddress);
rtpAddress.setPort(remotePort);
if (ShouldAcceptData(rtpAddress))
{
RTPRawPacket *pack = new RTPRawPacket((uint8_t *) m_rtcpBuffer, bytesRead, rtpAddress, curtime, false);
m_rawPacketQueueLock.lock();
m_rawPacketQueue.append(pack);
m_rawPacketQueueLock.unlock();
emit NewDataAvailable();
}
}
}
bool RTPUDPTransmitter::ShouldAcceptData(const RTPAddress& rtpAddress)
{
if (m_receivemode == RTPTransmitter::AcceptAll)
{
return true;
}
else if (m_receivemode == RTPTransmitter::AcceptSome)
{
std::list<RTPAddress>::iterator findIt = std::find(m_acceptList.begin(), m_acceptList.end(), rtpAddress);
return findIt != m_acceptList.end();
}
else if (m_receivemode == RTPTransmitter::IgnoreSome)
{
std::list<RTPAddress>::iterator findIt = std::find(m_ignoreList.begin(), m_ignoreList.end(), rtpAddress);
return findIt == m_ignoreList.end();
}
else
{
return false;
}
}
} // namespace

View File

@ -34,12 +34,17 @@
#define QRTPLIB_RTPUDPTRANSMITTER_H_
#include "rtptransmitter.h"
#include "util/export.h"
#include <QObject>
#include <QHostAddress>
#include <QNetworkInterface>
#include <QQueue>
#include <QMutex>
#include <stdint.h>
#include <list>
#include "util/export.h"
#define RTPUDPV4TRANS_HASHSIZE 8317
#define RTPUDPV4TRANS_DEFAULTPORTBASE 5000
#define RTPUDPV4TRANS_RTPRECEIVEBUFFER 32768
@ -64,8 +69,8 @@ public:
}
/** Sets the multicast interface IP address. */
void SetMulticastInterfaceIP(const QHostAddress& mcastGroupAddress) {
m_mcastGroupAddress = mcastGroupAddress;
void SetMulticastInterface(const QNetworkInterface& mcastInterface) {
m_mcastInterface = mcastInterface;
}
/** Sets the RTP portbase to \c pbase, which has to be an even number
@ -76,21 +81,6 @@ public:
m_portbase = pbase;
}
/** Passes a list of IP addresses which will be used as the local IP addresses. */
void SetLocalIPList(const std::list<QHostAddress>& iplist)
{
m_localIPs = iplist;
}
/** Clears the list of local IP addresses.
* Clears the list of local IP addresses. An empty list will make the transmission
* component itself determine the local IP addresses.
*/
void ClearLocalIPList()
{
m_localIPs.clear();
}
/** Returns the IP address which will be used to bind the sockets. */
QHostAddress GetBindIP() const
{
@ -98,9 +88,9 @@ public:
}
/** Returns the multicast interface IP address. */
QHostAddress GetMulticastInterfaceIP() const
QNetworkInterface GetMulticastInterface() const
{
return m_mcastGroupAddress;
return m_mcastInterface;
}
/** Returns the RTP portbase which will be used (default is 5000). */
@ -109,12 +99,6 @@ public:
return m_portbase;
}
/** Returns the list of local IP addresses. */
const std::list<QHostAddress> &GetLocalIPList() const
{
return m_localIPs;
}
/** Sets the RTP socket's send buffer size. */
void SetRTPSendBufferSize(int s)
{
@ -225,9 +209,8 @@ public:
private:
QHostAddress m_bindAddress;
QHostAddress m_mcastGroupAddress;
QNetworkInterface m_mcastInterface;
uint16_t m_portbase;
std::list<QHostAddress> m_localIPs;
int m_rtpsendbufsz, m_rtprecvbufsz;
int m_rtcpsendbufsz, m_rtcprecvbufsz;
bool m_rtcpmux;
@ -258,10 +241,15 @@ inline RTPUDPTransmissionParams::RTPUDPTransmissionParams() :
class QRTPLIB_API RTPUDPTransmissionInfo: public RTPTransmissionInfo
{
public:
RTPUDPTransmissionInfo(const std::list<QHostAddress>& iplist, QUdpSocket *rtpsock, QUdpSocket *rtcpsock, uint16_t rtpport, uint16_t rtcpport) :
RTPTransmissionInfo(RTPTransmitter::IPv4UDPProto)
RTPUDPTransmissionInfo(
QHostAddress localIP,
QUdpSocket *rtpsock,
QUdpSocket *rtcpsock,
uint16_t rtpport,
uint16_t rtcpport) :
RTPTransmissionInfo(RTPTransmitter::IPv4UDPProto)
{
m_localIPlist = iplist;
m_localIP = localIP;
m_rtpsocket = rtpsock;
m_rtcpsocket = rtcpsock;
m_rtpPort = rtpport;
@ -272,12 +260,6 @@ public:
{
}
/** Returns the list of IPv4 addresses the transmitter considers to be the local IP addresses. */
std::list<uint32_t> GetLocalIPList() const
{
return m_localIPlist;
}
/** Returns the socket descriptor used for receiving and transmitting RTP packets. */
QUdpSocket *GetRTPSocket() const
{
@ -302,7 +284,7 @@ public:
return m_rtcpPort;
}
private:
std::list<QHostAddress> m_localIPlist;
QHostAddress m_localIP;
QUdpSocket *m_rtpsocket, *m_rtcpsocket;
uint16_t m_rtpPort, m_rtcpPort;
};
@ -315,81 +297,79 @@ private:
* are described by the class RTPUDPTransmissionParams. The GetTransmissionInfo member function
* returns an instance of type RTPUDPTransmissionInfo.
*/
class QRTPLIB_API RTPUDPTransmitter: public RTPTransmitter
class QRTPLIB_API RTPUDPTransmitter: public QObject, public RTPTransmitter
{
Q_OBJECT
public:
RTPUDPTransmitter();
~RTPUDPTransmitter();
virtual ~RTPUDPTransmitter();
int Init();
int Create(std::size_t maxpacksize, const RTPTransmissionParams *transparams);
void Destroy();
RTPTransmissionInfo *GetTransmissionInfo();
void DeleteTransmissionInfo(RTPTransmissionInfo *inf);
virtual int Init();
virtual int Create(std::size_t maxpacksize, const RTPTransmissionParams *transparams);
virtual int BindSockets();
virtual void Destroy();
virtual RTPTransmissionInfo *GetTransmissionInfo();
virtual void DeleteTransmissionInfo(RTPTransmissionInfo *inf);
bool ComesFromThisTransmitter(const RTPAddress *addr);
std::size_t GetHeaderOverhead()
virtual bool ComesFromThisTransmitter(const RTPAddress& addr);
virtual std::size_t GetHeaderOverhead()
{
return RTPUDPTRANS_HEADERSIZE;
}
int Poll();
int WaitForIncomingData(const RTPTime &delay, bool *dataavailable = 0);
int AbortWait();
virtual int SendRTPData(const void *data, std::size_t len);
virtual int SendRTCPData(const void *data, std::size_t len);
int SendRTPData(const void *data, std::size_t len);
int SendRTCPData(const void *data, std::size_t len);
virtual int AddDestination(const RTPAddress &addr);
virtual int DeleteDestination(const RTPAddress &addr);
virtual void ClearDestinations();
int AddDestination(const RTPAddress &addr);
int DeleteDestination(const RTPAddress &addr);
void ClearDestinations();
virtual bool SupportsMulticasting();
virtual int JoinMulticastGroup(const RTPAddress &addr);
virtual int LeaveMulticastGroup(const RTPAddress &addr);
bool SupportsMulticasting();
int JoinMulticastGroup(const RTPAddress &addr);
int LeaveMulticastGroup(const RTPAddress &addr);
void LeaveAllMulticastGroups();
virtual int SetReceiveMode(RTPTransmitter::ReceiveMode m);
virtual int AddToIgnoreList(const RTPAddress &addr);
virtual int DeleteFromIgnoreList(const RTPAddress &addr);
virtual void ClearIgnoreList();
virtual int AddToAcceptList(const RTPAddress &addr);
virtual int DeleteFromAcceptList(const RTPAddress &addr);
virtual void ClearAcceptList();
virtual int SetMaximumPacketSize(std::size_t s);
int SetReceiveMode(RTPTransmitter::ReceiveMode m);
int AddToIgnoreList(const RTPAddress &addr);
int DeleteFromIgnoreList(const RTPAddress &addr);
void ClearIgnoreList();
int AddToAcceptList(const RTPAddress &addr);
int DeleteFromAcceptList(const RTPAddress &addr);
void ClearAcceptList();
int SetMaximumPacketSize(std::size_t s);
bool NewDataAvailable(); // TODO: emit signal instead
RTPRawPacket *GetNextPacket(); // TODO: use a queue
virtual RTPRawPacket *GetNextPacket();
private:
int CreateLocalIPList();
bool GetLocalIPList_Interfaces();
void GetLocalIPList_DNS();
void AddLoopbackAddress();
void FlushPackets();
int ProcessAddAcceptIgnoreEntry(uint32_t ip, uint16_t port);
int ProcessDeleteAcceptIgnoreEntry(uint32_t ip, uint16_t port);
bool ShouldAcceptData(uint32_t srcip, uint16_t srcport);
void ClearAcceptIgnoreInfo();
bool m_init;
bool m_created;
bool m_waitingfordata;
QUdpSocket *m_rtpsock, *m_rtcpsock;
QHostAddress m_mcastifaceIP;
QHostAddress m_localIP;
QHostAddress m_localIP; //!< from parameters bind IP
QNetworkInterface m_multicastInterface; //!< from parameters multicast interface
uint16_t m_rtpPort, m_rtcpPort;
RTPTransmitter::ReceiveMode m_receivemode;
uint8_t *m_localhostname;
std::size_t m_localhostnamelength;
std::list<RTPRawPacket*> m_rawpacketlist;
bool m_supportsmulticasting;
std::size_t m_maxpacksize;
static const std::size_t m_absoluteMaxPackSize = 65535;
char m_rtpBuffer[m_absoluteMaxPackSize];
char m_rtcpBuffer[m_absoluteMaxPackSize];
std::list<RTPAddress> m_destinations;
std::list<RTPAddress> m_acceptList;
std::list<RTPAddress> m_ignoreList;
QQueue<RTPRawPacket*> m_rawPacketQueue;
QMutex m_rawPacketQueueLock;
bool m_closesocketswhendone;
bool ShouldAcceptData(const RTPAddress& address);
private slots:
void readRTPPendingDatagrams();
void readRTCPPendingDatagrams();
signals:
void NewDataAvailable();
};