Compare commits

..

No commits in common. "e342abe2f57646bcdb287a8dba23b9f200261639" and "c3c59ddf03b60a2a09657b7b0a5e2b85f0d51171" have entirely different histories.

12 changed files with 403 additions and 322 deletions

View File

@ -184,3 +184,80 @@ void RtpDump::flush()
} }
#endif #endif
// -------------- MediaStreamId --------------------
bool MediaStreamId::operator < (const MediaStreamId& right) const
{
if (mSsrcIsId)
return std::tie(mSSRC, mSource, mDestination) < std::tie(right.mSSRC, right.mSource, right.mDestination);
else
return std::tie(mSource, mDestination) < std::tie(right.mSource, right.mDestination);
}
bool MediaStreamId::operator == (const MediaStreamId& right) const
{
if (mSsrcIsId)
return std::tie(mSSRC, mSource, mDestination) == std::tie(right.mSSRC, right.mSource, right.mDestination);
else
return std::tie(mSource, mDestination) == std::tie(right.mSource, right.mDestination);
}
std::string MediaStreamId::toString() const
{
std::ostringstream oss;
oss << "src: " << mSource.toStdString() <<
" dst: " << mDestination.toStdString() <<
" ssrc: " << StringHelper::toHex(mSSRC);
return oss.str();
}
void writeToJson(const MediaStreamId& id, std::ostringstream& oss)
{
oss << " \"src\": \"" << id.mSource.toStdString() << "\"," << std::endl
<< " \"dst\": \"" << id.mDestination.toStdString() << "\"," << std::endl
<< " \"ssrc\": \"" << StringHelper::toHex(id.mSSRC) << "\"," << std::endl
#if !defined(USE_NULL_UUID)
<< " \"link_id\": \"" << id.mLinkId.toString() << "\"" << std::endl
#endif
;
}
std::string MediaStreamId::getDetectDescription() const
{
std::ostringstream oss;
oss << "{\"event\": \"stream_detected\"," << std::endl;
writeToJson(*this, oss);
oss << "}";
return oss.str();
}
std::string MediaStreamId::getFinishDescription() const
{
std::ostringstream oss;
oss << "{" << std::endl
<< " \"event\": \"stream_finished\", " << std::endl;
writeToJson(*this, oss);
oss << "}";
return oss.str();
}
MediaStreamId& MediaStreamId::operator = (const MediaStreamId& src)
{
this->mDestination = src.mDestination;
this->mSource = src.mSource;
this->mLinkId = src.mLinkId;
this->mSSRC = src.mSSRC;
this->mSsrcIsId = src.mSsrcIsId;
return *this;
}
std::ostream& operator << (std::ostream& output, const MediaStreamId& id)
{
return (output << id.toString());
}

View File

@ -72,4 +72,22 @@ public:
}; };
#endif #endif
struct MediaStreamId
{
InternetAddress mSource;
InternetAddress mDestination;
uint32_t mSSRC = 0;
bool mSsrcIsId = true;
Uuid mLinkId;
bool operator < (const MediaStreamId& s2) const;
bool operator == (const MediaStreamId& right) const;
std::string toString() const;
std::string getDetectDescription() const;
std::string getFinishDescription() const;
MediaStreamId& operator = (const MediaStreamId& src);
};
std::ostream& operator << (std::ostream& output, const MediaStreamId& id);
#endif #endif

View File

@ -80,8 +80,6 @@ if (CMAKE_SYSTEM MATCHES "Windows*")
endif() endif()
add_library(media_lib ${SOURCES}) add_library(media_lib ${SOURCES})
# Depending on ice stack library to provide bit level operations
target_link_libraries(media_lib PUBLIC ice_stack)
target_include_directories(media_lib target_include_directories(media_lib
PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../../libs/ PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../../libs/

View File

@ -67,7 +67,7 @@ void JitterStatistics::process(jrtplib::RTPPacket* packet, int rate)
Statistics::Statistics() Statistics::Statistics()
:mReceived(0), mSent(0), mReceivedRtp(0), mSentRtp(0), :mReceived(0), mSent(0), mReceivedRtp(0), mSentRtp(0),
mReceivedRtcp(0), mSentRtcp(0), mDuplicatedRtp(0), mOldRtp(0), mIllegalRtp(0), mReceivedRtcp(0), mSentRtcp(0), mDuplicatedRtp(0), mOldRtp(0), mIllegalRtp(0),
mPacketLoss(0), mJitter(0.0), mAudioTime(0), mSsrc(0), mPacketDropped(0), mDecodedAudio(0) mPacketLoss(0), mJitter(0.0), mAudioTime(0), mSsrc(0), mPacketDropped(0)
{ {
mBitrateSwitchCounter = 0; mBitrateSwitchCounter = 0;
memset(mLoss, 0, sizeof mLoss); memset(mLoss, 0, sizeof mLoss);
@ -95,7 +95,7 @@ void Statistics::reset()
mJitter = 0.0; mJitter = 0.0;
mAudioTime = 0; mAudioTime = 0;
mPacketDropped = 0; mPacketDropped = 0;
mDecodedAudio = 0;
memset(mLoss, 0, sizeof mLoss); memset(mLoss, 0, sizeof mLoss);
} }
@ -179,7 +179,7 @@ Statistics& Statistics::operator += (const Statistics& src)
mPacketLoss += src.mPacketLoss; mPacketLoss += src.mPacketLoss;
mPacketDropped += src.mPacketDropped; mPacketDropped += src.mPacketDropped;
mAudioTime += src.mAudioTime; mAudioTime += src.mAudioTime;
mDecodedAudio += src.mDecodedAudio;
for (auto codecStat: src.mCodecCount) for (auto codecStat: src.mCodecCount)
{ {
@ -230,7 +230,6 @@ Statistics& Statistics::operator -= (const Statistics& src)
mOldRtp -= src.mOldRtp; mOldRtp -= src.mOldRtp;
mPacketLoss -= src.mPacketLoss; mPacketLoss -= src.mPacketLoss;
mPacketDropped -= src.mPacketDropped; mPacketDropped -= src.mPacketDropped;
mDecodedAudio -= src.mDecodedAudio;
mAudioTime -= src.mAudioTime; mAudioTime -= src.mAudioTime;
for (auto codecStat: src.mCodecCount) for (auto codecStat: src.mCodecCount)

View File

@ -63,8 +63,6 @@ public:
mPacketDropped, // Number of dropped packets (due to time unsync when playing)б mPacketDropped, // Number of dropped packets (due to time unsync when playing)б
mIllegalRtp; // Number of rtp packets with bad payload type mIllegalRtp; // Number of rtp packets with bad payload type
size_t mDecodedAudio; // Size of decoded audio bytes
TestResult<float> mDecodingInterval, // Average interval on call to packet decode TestResult<float> mDecodingInterval, // Average interval on call to packet decode
mDecodeRequested, // Average amount of requested audio frames to play mDecodeRequested, // Average amount of requested audio frames to play
mPacketInterval; // Average interval between packet adding to jitter buffer mPacketInterval; // Average interval between packet adding to jitter buffer
@ -100,10 +98,10 @@ public:
Statistics& operator -= (const Statistics& src); Statistics& operator -= (const Statistics& src);
float mNetworkMos = 0.0; float mNetworkMos = 0.0;
// #if defined(USE_PVQA_LIBRARY) && !defined(PVQA_SERVER) #if defined(USE_PVQA_LIBRARY) && !defined(PVQA_SERVER)
// float mPvqaMos = 0.0; float mPvqaMos = 0.0;
//std::string mPvqaReport; std::string mPvqaReport;
// #endif #endif
std::string toString() const; std::string toString() const;
}; };

View File

@ -201,6 +201,7 @@ void Logger::beginLine(LogLevel level, const char* filename, int linenumber, con
void void
Logger::endLine() Logger::endLine()
{ {
*mStream << std::endl;
*mStream << std::flush; *mStream << std::flush;
mStream->flush(); mStream->flush();
@ -212,7 +213,7 @@ Logger::endLine()
result << time_buffer << ":" << (unix_timestamp_ms.count() % 1000 ) << "\t" << " | " << std::setw(8) << ThreadInfo::currentThread() << " | " << std::setw(30) result << time_buffer << ":" << (unix_timestamp_ms.count() % 1000 ) << "\t" << " | " << std::setw(8) << ThreadInfo::currentThread() << " | " << std::setw(30)
<< mFilename.c_str() << " | " << std::setw(4) << mLine << " | " << std::setw(12) << mSubsystem.c_str() << " | " << mFilename.c_str() << " | " << std::setw(4) << mLine << " | " << std::setw(12) << mSubsystem.c_str() << " | "
<< mStream->str().c_str() << std::endl; << mStream->str().c_str();
std::string t = result.str(); std::string t = result.str();
if (mUseDebugWindow) { if (mUseDebugWindow) {

View File

@ -86,14 +86,8 @@ protected:
class LogLock class LogLock
{ {
public: public:
LogLock(LogGuard& g) :mGuard(g) LogLock(LogGuard& g) :mGuard(g) { mGuard.Lock(); }
{ ~LogLock() { mGuard.Unlock(); }
mGuard.Lock();
}
~LogLock()
{
mGuard.Unlock();
}
protected: protected:
LogGuard& mGuard; LogGuard& mGuard;

View File

@ -91,4 +91,4 @@ set(JRTPLIB_SOURCES
rtpexternaltransmitter.cpp) rtpexternaltransmitter.cpp)
add_library(jrtplib STATIC ${JRTPLIB_SOURCES}) add_library(jrtplib STATIC ${JRTPLIB_SOURCES})
target_include_directories(jrtplib PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})

View File

@ -53,56 +53,56 @@ class RTCPPacket;
class JRTPLIB_IMPORTEXPORT RTCPCompoundPacket : public RTPMemoryObject class JRTPLIB_IMPORTEXPORT RTCPCompoundPacket : public RTPMemoryObject
{ {
public: public:
/** Creates an RTCPCompoundPacket instance from the data in \c rawpack, installing a memory manager if specified. */ /** Creates an RTCPCompoundPacket instance from the data in \c rawpack, installing a memory manager if specified. */
RTCPCompoundPacket(RTPRawPacket &rawpack, RTPMemoryManager *memmgr = 0); RTCPCompoundPacket(RTPRawPacket &rawpack, RTPMemoryManager *memmgr = 0);
/** 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.
* Creates an RTCPCompoundPacket instance from the data in \c packet}, with size \c len. The \c deletedata * 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 * 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. * specified, a memory manager will be installed.
*/ */
RTCPCompoundPacket(uint8_t *packet, size_t len, bool deletedata = true, RTPMemoryManager *memmgr = 0); RTCPCompoundPacket(uint8_t *packet, size_t len, bool deletedata = true, RTPMemoryManager *memmgr = 0);
protected: protected:
RTCPCompoundPacket(RTPMemoryManager *memmgr); // this is for the compoundpacket builder RTCPCompoundPacket(RTPMemoryManager *memmgr); // this is for the compoundpacket builder
public: public:
virtual ~RTCPCompoundPacket(); virtual ~RTCPCompoundPacket();
/** Checks if the RTCP compound packet was created successfully. /** Checks if the RTCP compound packet was created successfully.
* If the raw packet data in the constructor could not be parsed, this function returns the error code of * If the raw packet data in the constructor could not be parsed, this function returns the error code of
* what went wrong. If the packet had an invalid format, the return value is \c ERR_RTP_RTCPCOMPOUND_INVALIDPACKET. * what went wrong. If the packet had an invalid format, the return value is \c ERR_RTP_RTCPCOMPOUND_INVALIDPACKET.
*/ */
int GetCreationError() { return error; } int GetCreationError() { return error; }
/** Returns a pointer to the data of the entire RTCP compound packet. */ /** Returns a pointer to the data of the entire RTCP compound packet. */
const uint8_t *GetCompoundPacketData() { return compoundpacket; } const uint8_t *GetCompoundPacketData() { return compoundpacket; }
/** Returns the size of the entire RTCP compound packet. */ /** Returns the size of the entire RTCP compound packet. */
size_t GetCompoundPacketLength() { return compoundpacketlength; } size_t GetCompoundPacketLength() { return compoundpacketlength; }
/** Starts the iteration over the individual RTCP packets in the RTCP compound packet. */ /** Starts the iteration over the individual RTCP packets in the RTCP compound packet. */
void GotoFirstPacket() { rtcppackit = rtcppacklist.begin(); } void GotoFirstPacket() { rtcppackit = rtcppacklist.begin(); }
/** Returns a pointer to the next individual RTCP packet. /** Returns a pointer to the next individual RTCP packet.
* Returns a pointer to the next individual RTCP packet. Note that no \c delete call may be done * Returns a pointer to the next individual RTCP packet. Note that no \c delete call may be done
* on the RTCPPacket instance which is returned. * on the RTCPPacket instance which is returned.
*/ */
RTCPPacket *GetNextPacket() { if (rtcppackit == rtcppacklist.end()) return 0; RTCPPacket *p = *rtcppackit; rtcppackit++; return p; } RTCPPacket *GetNextPacket() { if (rtcppackit == rtcppacklist.end()) return 0; RTCPPacket *p = *rtcppackit; rtcppackit++; return p; }
#ifdef RTPDEBUG #ifdef RTPDEBUG
void Dump(); void Dump();
#endif // RTPDEBUG #endif // RTPDEBUG
protected: protected:
void ClearPacketList(); void ClearPacketList();
int ParseData(uint8_t *packet, size_t len); int ParseData(uint8_t *packet, size_t len);
int error; int error;
const uint8_t *compoundpacket; const uint8_t *compoundpacket;
size_t compoundpacketlength; size_t compoundpacketlength;
bool deletepacket; bool deletepacket;
std::list<RTCPPacket *> rtcppacklist; std::list<RTCPPacket *> rtcppacklist;
std::list<RTCPPacket *>::const_iterator rtcppackit; std::list<RTCPPacket *>::const_iterator rtcppackit;
}; };
} // end namespace } // end namespace

View File

@ -36,12 +36,12 @@
#include "rtperrors.h" #include "rtperrors.h"
#include "rtprawpacket.h" #include "rtprawpacket.h"
#if ! (defined(WIN32) || defined(_WIN32_WCE)) #if ! (defined(WIN32) || defined(_WIN32_WCE))
#include <netinet/in.h> #include <netinet/in.h>
#include <string.h> #include <string.h>
#endif // WIN32 #endif // WIN32
#ifdef RTPDEBUG #ifdef RTPDEBUG
#include <stdio.h> #include <stdio.h>
#endif // RTPDEBUG #endif // RTPDEBUG
#include "rtpdebug.h" #include "rtpdebug.h"
@ -51,310 +51,306 @@ namespace jrtplib
void RTPPacket::Clear() void RTPPacket::Clear()
{ {
hasextension = false; hasextension = false;
hasmarker = false; hasmarker = false;
numcsrcs = 0; numcsrcs = 0;
payloadtype = 0; payloadtype = 0;
extseqnr = 0; extseqnr = 0;
timestamp = 0; timestamp = 0;
ssrc = 0; ssrc = 0;
packet = 0; packet = 0;
payload = 0; payload = 0;
packetlength = 0; packetlength = 0;
payloadlength = 0; payloadlength = 0;
extid = 0; extid = 0;
extension = 0; extension = 0;
extensionlength = 0; extensionlength = 0;
error = 0; error = 0;
externalbuffer = false; externalbuffer = false;
} }
RTPPacket::RTPPacket(RTPRawPacket &rawpack,RTPMemoryManager *mgr) : RTPMemoryObject(mgr),receivetime(rawpack.GetReceiveTime()) RTPPacket::RTPPacket(RTPRawPacket &rawpack,RTPMemoryManager *mgr) : RTPMemoryObject(mgr),receivetime(rawpack.GetReceiveTime())
{ {
Clear(); Clear();
error = ParseRawPacket(rawpack); error = ParseRawPacket(rawpack);
} }
RTPPacket::RTPPacket(uint8_t payloadtype,const void *payloaddata,size_t payloadlen,uint16_t seqnr, RTPPacket::RTPPacket(uint8_t payloadtype,const void *payloaddata,size_t payloadlen,uint16_t seqnr,
uint32_t timestamp,uint32_t ssrc,bool gotmarker,uint8_t numcsrcs,const uint32_t *csrcs, 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, bool gotextension,uint16_t extensionid,uint16_t extensionlen_numwords,const void *extensiondata,
size_t maxpacksize, RTPMemoryManager *mgr) : RTPMemoryObject(mgr),receivetime(0,0) size_t maxpacksize, RTPMemoryManager *mgr) : RTPMemoryObject(mgr),receivetime(0,0)
{ {
Clear(); Clear();
error = BuildPacket(payloadtype,payloaddata,payloadlen,seqnr,timestamp,ssrc,gotmarker,numcsrcs, error = BuildPacket(payloadtype,payloaddata,payloadlen,seqnr,timestamp,ssrc,gotmarker,numcsrcs,
csrcs,gotextension,extensionid,extensionlen_numwords,extensiondata,0,maxpacksize); csrcs,gotextension,extensionid,extensionlen_numwords,extensiondata,0,maxpacksize);
} }
RTPPacket::RTPPacket(uint8_t payloadtype,const void *payloaddata,size_t payloadlen,uint16_t seqnr, RTPPacket::RTPPacket(uint8_t payloadtype,const void *payloaddata,size_t payloadlen,uint16_t seqnr,
uint32_t timestamp,uint32_t ssrc,bool gotmarker,uint8_t numcsrcs,const uint32_t *csrcs, 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, bool gotextension,uint16_t extensionid,uint16_t extensionlen_numwords,const void *extensiondata,
void *buffer,size_t buffersize, RTPMemoryManager *mgr) : RTPMemoryObject(mgr),receivetime(0,0) void *buffer,size_t buffersize, RTPMemoryManager *mgr) : RTPMemoryObject(mgr),receivetime(0,0)
{ {
Clear(); Clear();
if (buffer == 0) if (buffer == 0)
error = ERR_RTP_PACKET_EXTERNALBUFFERNULL; error = ERR_RTP_PACKET_EXTERNALBUFFERNULL;
else if (buffersize <= 0) else if (buffersize <= 0)
error = ERR_RTP_PACKET_ILLEGALBUFFERSIZE; error = ERR_RTP_PACKET_ILLEGALBUFFERSIZE;
else else
error = BuildPacket(payloadtype,payloaddata,payloadlen,seqnr,timestamp,ssrc,gotmarker,numcsrcs, error = BuildPacket(payloadtype,payloaddata,payloadlen,seqnr,timestamp,ssrc,gotmarker,numcsrcs,
csrcs,gotextension,extensionid,extensionlen_numwords,extensiondata,buffer,buffersize); csrcs,gotextension,extensionid,extensionlen_numwords,extensiondata,buffer,buffersize);
} }
RTPPacket::~RTPPacket() RTPPacket::~RTPPacket()
{ {
if (packet && !externalbuffer) if (packet && !externalbuffer)
{ {
RTPDeleteByteArray(packet,GetMemoryManager()); RTPDeleteByteArray(packet,GetMemoryManager());
} }
} }
int RTPPacket::ParseRawPacket(RTPRawPacket &rawpack) int RTPPacket::ParseRawPacket(RTPRawPacket &rawpack)
{ {
uint8_t *packetbytes; uint8_t *packetbytes;
size_t packetlen; size_t packetlen;
uint8_t payloadtype; uint8_t payloadtype;
RTPHeader *rtpheader; RTPHeader *rtpheader;
bool marker; bool marker;
int csrccount; int csrccount;
bool hasextension; bool hasextension;
int payloadoffset,payloadlength; int payloadoffset,payloadlength;
int numpadbytes; int numpadbytes;
RTPExtensionHeader *rtpextheader; RTPExtensionHeader *rtpextheader;
uint16_t exthdrlen; uint16_t exthdrlen;
if (!rawpack.IsRTP()) // If we didn't receive it on the RTP port, we'll ignore it if (!rawpack.IsRTP()) // If we didn't receive it on the RTP port, we'll ignore it
return ERR_RTP_PACKET_INVALIDPACKET; return ERR_RTP_PACKET_INVALIDPACKET;
// The length should be at least the size of the RTP header // The length should be at least the size of the RTP header
packetlen = rawpack.GetDataLength(); packetlen = rawpack.GetDataLength();
if (packetlen < sizeof(RTPHeader)) if (packetlen < sizeof(RTPHeader))
return ERR_RTP_PACKET_INVALIDPACKET; return ERR_RTP_PACKET_INVALIDPACKET;
packetbytes = (uint8_t *)rawpack.GetData(); packetbytes = (uint8_t *)rawpack.GetData();
rtpheader = (RTPHeader *)packetbytes; rtpheader = (RTPHeader *)packetbytes;
// The version number should be correct // The version number should be correct
if (rtpheader->version != RTP_VERSION) if (rtpheader->version != RTP_VERSION)
return ERR_RTP_PACKET_INVALIDPACKET; return ERR_RTP_PACKET_INVALIDPACKET;
// We'll check if this is possibly a RTCP packet. For this to be possible // We'll check if this is possibly a RTCP packet. For this to be possible
// the marker bit and payload type combined should be either an SR or RR // the marker bit and payload type combined should be either an SR or RR
// identifier // identifier
marker = (rtpheader->marker == 0)?false:true; marker = (rtpheader->marker == 0)?false:true;
payloadtype = rtpheader->payloadtype; payloadtype = rtpheader->payloadtype;
if (marker) if (marker)
{ {
if (payloadtype == (RTP_RTCPTYPE_SR & 127)) // don't check high bit (this was the marker!!) if (payloadtype == (RTP_RTCPTYPE_SR & 127)) // don't check high bit (this was the marker!!)
return ERR_RTP_PACKET_INVALIDPACKET; return ERR_RTP_PACKET_INVALIDPACKET;
if (payloadtype == (RTP_RTCPTYPE_RR & 127)) if (payloadtype == (RTP_RTCPTYPE_RR & 127))
return ERR_RTP_PACKET_INVALIDPACKET; return ERR_RTP_PACKET_INVALIDPACKET;
} }
csrccount = rtpheader->csrccount; csrccount = rtpheader->csrccount;
payloadoffset = sizeof(RTPHeader)+(int)(csrccount*sizeof(uint32_t)); payloadoffset = sizeof(RTPHeader)+(int)(csrccount*sizeof(uint32_t));
if ((size_t)payloadoffset > packetlen)
return ERR_RTP_PACKET_INVALIDPACKET;
if (rtpheader->padding) // adjust payload length to take padding into account if (rtpheader->padding) // adjust payload length to take padding into account
{ {
numpadbytes = (int)packetbytes[packetlen-1]; // last byte contains number of padding bytes numpadbytes = (int)packetbytes[packetlen-1]; // last byte contains number of padding bytes
if (numpadbytes <= 0) if (numpadbytes <= 0)
return ERR_RTP_PACKET_INVALIDPACKET; return ERR_RTP_PACKET_INVALIDPACKET;
} }
else else
numpadbytes = 0; numpadbytes = 0;
hasextension = (rtpheader->extension == 0)?false:true; hasextension = (rtpheader->extension == 0)?false:true;
if (hasextension) // got header extension if (hasextension) // got header extension
{ {
rtpextheader = (RTPExtensionHeader *)(packetbytes+payloadoffset); rtpextheader = (RTPExtensionHeader *)(packetbytes+payloadoffset);
payloadoffset += sizeof(RTPExtensionHeader); payloadoffset += sizeof(RTPExtensionHeader);
if ((size_t)payloadoffset > packetlen) exthdrlen = ntohs(rtpextheader->length);
return ERR_RTP_PACKET_INVALIDPACKET; payloadoffset += ((int)exthdrlen)*sizeof(uint32_t);
exthdrlen = ntohs(rtpextheader->length); }
payloadoffset += ((int)exthdrlen)*sizeof(uint32_t); else
} {
else rtpextheader = 0;
{ exthdrlen = 0;
rtpextheader = 0; }
exthdrlen = 0;
}
payloadlength = packetlen-numpadbytes-payloadoffset; payloadlength = packetlen-numpadbytes-payloadoffset;
if (payloadlength < 0) if (payloadlength < 0)
return ERR_RTP_PACKET_INVALIDPACKET; return ERR_RTP_PACKET_INVALIDPACKET;
// Now, we've got a valid packet, so we can create a new instance of RTPPacket // Now, we've got a valid packet, so we can create a new instance of RTPPacket
// and fill in the members // and fill in the members
RTPPacket::hasextension = hasextension; RTPPacket::hasextension = hasextension;
if (hasextension) if (hasextension)
{ {
RTPPacket::extid = ntohs(rtpextheader->extid); RTPPacket::extid = ntohs(rtpextheader->extid);
RTPPacket::extensionlength = ((int)ntohs(rtpextheader->length))*sizeof(uint32_t); RTPPacket::extensionlength = ((int)ntohs(rtpextheader->length))*sizeof(uint32_t);
RTPPacket::extension = ((uint8_t *)rtpextheader)+sizeof(RTPExtensionHeader); RTPPacket::extension = ((uint8_t *)rtpextheader)+sizeof(RTPExtensionHeader);
} }
RTPPacket::hasmarker = marker; RTPPacket::hasmarker = marker;
RTPPacket::numcsrcs = csrccount; RTPPacket::numcsrcs = csrccount;
RTPPacket::payloadtype = payloadtype; RTPPacket::payloadtype = payloadtype;
// Note: we don't fill in the EXTENDED sequence number here, since we // Note: we don't fill in the EXTENDED sequence number here, since we
// don't have information about the source here. We just fill in the low // don't have information about the source here. We just fill in the low
// 16 bits // 16 bits
RTPPacket::extseqnr = (uint32_t)ntohs(rtpheader->sequencenumber); RTPPacket::extseqnr = (uint32_t)ntohs(rtpheader->sequencenumber);
RTPPacket::timestamp = ntohl(rtpheader->timestamp); RTPPacket::timestamp = ntohl(rtpheader->timestamp);
RTPPacket::ssrc = ntohl(rtpheader->ssrc); RTPPacket::ssrc = ntohl(rtpheader->ssrc);
RTPPacket::packet = packetbytes; RTPPacket::packet = packetbytes;
RTPPacket::payload = packetbytes+payloadoffset; RTPPacket::payload = packetbytes+payloadoffset;
RTPPacket::packetlength = packetlen; RTPPacket::packetlength = packetlen;
RTPPacket::payloadlength = payloadlength; RTPPacket::payloadlength = payloadlength;
// We'll zero the data of the raw packet, since we're using it here now! // We'll zero the data of the raw packet, since we're using it here now!
rawpack.ZeroData(); rawpack.ZeroData();
return 0; return 0;
} }
uint32_t RTPPacket::GetCSRC(int num) const uint32_t RTPPacket::GetCSRC(int num) const
{ {
if (num >= numcsrcs) if (num >= numcsrcs)
return 0; return 0;
uint8_t *csrcpos; uint8_t *csrcpos;
uint32_t *csrcval_nbo; uint32_t *csrcval_nbo;
uint32_t csrcval_hbo; uint32_t csrcval_hbo;
csrcpos = packet+sizeof(RTPHeader)+num*sizeof(uint32_t); csrcpos = packet+sizeof(RTPHeader)+num*sizeof(uint32_t);
csrcval_nbo = (uint32_t *)csrcpos; csrcval_nbo = (uint32_t *)csrcpos;
csrcval_hbo = ntohl(*csrcval_nbo); csrcval_hbo = ntohl(*csrcval_nbo);
return csrcval_hbo; return csrcval_hbo;
} }
int RTPPacket::BuildPacket(uint8_t payloadtype,const void *payloaddata,size_t payloadlen,uint16_t seqnr, int RTPPacket::BuildPacket(uint8_t payloadtype,const void *payloaddata,size_t payloadlen,uint16_t seqnr,
uint32_t timestamp,uint32_t ssrc,bool gotmarker,uint8_t numcsrcs,const uint32_t *csrcs, 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, bool gotextension,uint16_t extensionid,uint16_t extensionlen_numwords,const void *extensiondata,
void *buffer,size_t maxsize) void *buffer,size_t maxsize)
{ {
if (numcsrcs > RTP_MAXCSRCS) if (numcsrcs > RTP_MAXCSRCS)
return ERR_RTP_PACKET_TOOMANYCSRCS; return ERR_RTP_PACKET_TOOMANYCSRCS;
if (payloadtype > 127) // high bit should not be used if (payloadtype > 127) // high bit should not be used
return ERR_RTP_PACKET_BADPAYLOADTYPE; return ERR_RTP_PACKET_BADPAYLOADTYPE;
if (payloadtype == 72 || payloadtype == 73) // could cause confusion with rtcp types if (payloadtype == 72 || payloadtype == 73) // could cause confusion with rtcp types
return ERR_RTP_PACKET_BADPAYLOADTYPE; return ERR_RTP_PACKET_BADPAYLOADTYPE;
packetlength = sizeof(RTPHeader); packetlength = sizeof(RTPHeader);
packetlength += sizeof(uint32_t)*((size_t)numcsrcs); packetlength += sizeof(uint32_t)*((size_t)numcsrcs);
if (gotextension) if (gotextension)
{ {
packetlength += sizeof(RTPExtensionHeader); packetlength += sizeof(RTPExtensionHeader);
packetlength += sizeof(uint32_t)*((size_t)extensionlen_numwords); packetlength += sizeof(uint32_t)*((size_t)extensionlen_numwords);
} }
packetlength += payloadlen; packetlength += payloadlen;
if (maxsize > 0 && packetlength > maxsize) if (maxsize > 0 && packetlength > maxsize)
{ {
packetlength = 0; packetlength = 0;
return ERR_RTP_PACKET_DATAEXCEEDSMAXSIZE; return ERR_RTP_PACKET_DATAEXCEEDSMAXSIZE;
} }
// Ok, now we'll just fill in... // Ok, now we'll just fill in...
RTPHeader *rtphdr; RTPHeader *rtphdr;
if (buffer == 0) if (buffer == 0)
{ {
packet = RTPNew(GetMemoryManager(),RTPMEM_TYPE_BUFFER_RTPPACKET) uint8_t [packetlength]; packet = RTPNew(GetMemoryManager(),RTPMEM_TYPE_BUFFER_RTPPACKET) uint8_t [packetlength];
if (packet == 0) if (packet == 0)
{ {
packetlength = 0; packetlength = 0;
return ERR_RTP_OUTOFMEM; return ERR_RTP_OUTOFMEM;
} }
externalbuffer = false; externalbuffer = false;
} }
else else
{ {
packet = (uint8_t *)buffer; packet = (uint8_t *)buffer;
externalbuffer = true; externalbuffer = true;
} }
RTPPacket::hasmarker = gotmarker; RTPPacket::hasmarker = gotmarker;
RTPPacket::hasextension = gotextension; RTPPacket::hasextension = gotextension;
RTPPacket::numcsrcs = numcsrcs; RTPPacket::numcsrcs = numcsrcs;
RTPPacket::payloadtype = payloadtype; RTPPacket::payloadtype = payloadtype;
RTPPacket::extseqnr = (uint32_t)seqnr; RTPPacket::extseqnr = (uint32_t)seqnr;
RTPPacket::timestamp = timestamp; RTPPacket::timestamp = timestamp;
RTPPacket::ssrc = ssrc; RTPPacket::ssrc = ssrc;
RTPPacket::payloadlength = payloadlen; RTPPacket::payloadlength = payloadlen;
RTPPacket::extid = extensionid; RTPPacket::extid = extensionid;
RTPPacket::extensionlength = ((size_t)extensionlen_numwords)*sizeof(uint32_t); RTPPacket::extensionlength = ((size_t)extensionlen_numwords)*sizeof(uint32_t);
rtphdr = (RTPHeader *)packet; rtphdr = (RTPHeader *)packet;
rtphdr->version = RTP_VERSION; rtphdr->version = RTP_VERSION;
rtphdr->padding = 0; rtphdr->padding = 0;
if (gotmarker) if (gotmarker)
rtphdr->marker = 1; rtphdr->marker = 1;
else else
rtphdr->marker = 0; rtphdr->marker = 0;
if (gotextension) if (gotextension)
rtphdr->extension = 1; rtphdr->extension = 1;
else else
rtphdr->extension = 0; rtphdr->extension = 0;
rtphdr->csrccount = numcsrcs; rtphdr->csrccount = numcsrcs;
rtphdr->payloadtype = payloadtype&127; // make sure high bit isn't set rtphdr->payloadtype = payloadtype&127; // make sure high bit isn't set
rtphdr->sequencenumber = htons(seqnr); rtphdr->sequencenumber = htons(seqnr);
rtphdr->timestamp = htonl(timestamp); rtphdr->timestamp = htonl(timestamp);
rtphdr->ssrc = htonl(ssrc); rtphdr->ssrc = htonl(ssrc);
uint32_t *curcsrc; uint32_t *curcsrc;
int i; int i;
curcsrc = (uint32_t *)(packet+sizeof(RTPHeader)); curcsrc = (uint32_t *)(packet+sizeof(RTPHeader));
for (i = 0 ; i < numcsrcs ; i++,curcsrc++) for (i = 0 ; i < numcsrcs ; i++,curcsrc++)
*curcsrc = htonl(csrcs[i]); *curcsrc = htonl(csrcs[i]);
payload = packet+sizeof(RTPHeader)+((size_t)numcsrcs)*sizeof(uint32_t); payload = packet+sizeof(RTPHeader)+((size_t)numcsrcs)*sizeof(uint32_t);
if (gotextension) if (gotextension)
{ {
RTPExtensionHeader *rtpexthdr = (RTPExtensionHeader *)payload; RTPExtensionHeader *rtpexthdr = (RTPExtensionHeader *)payload;
rtpexthdr->extid = htons(extensionid); rtpexthdr->extid = htons(extensionid);
rtpexthdr->length = htons((uint16_t)extensionlen_numwords); rtpexthdr->length = htons((uint16_t)extensionlen_numwords);
payload += sizeof(RTPExtensionHeader); payload += sizeof(RTPExtensionHeader);
memcpy(payload,extensiondata,RTPPacket::extensionlength); memcpy(payload,extensiondata,RTPPacket::extensionlength);
payload += RTPPacket::extensionlength; payload += RTPPacket::extensionlength;
} }
memcpy(payload,payloaddata,payloadlen); memcpy(payload,payloaddata,payloadlen);
return 0; return 0;
} }
#ifdef RTPDEBUG #ifdef RTPDEBUG
void RTPPacket::Dump() void RTPPacket::Dump()
{ {
int i; int i;
printf("Payload type: %d\n",(int)GetPayloadType()); printf("Payload type: %d\n",(int)GetPayloadType());
printf("Extended sequence number: 0x%08x\n",GetExtendedSequenceNumber()); printf("Extended sequence number: 0x%08x\n",GetExtendedSequenceNumber());
printf("Timestamp: 0x%08x\n",GetTimestamp()); printf("Timestamp: 0x%08x\n",GetTimestamp());
printf("SSRC: 0x%08x\n",GetSSRC()); printf("SSRC: 0x%08x\n",GetSSRC());
printf("Marker: %s\n",HasMarker()?"yes":"no"); printf("Marker: %s\n",HasMarker()?"yes":"no");
printf("CSRC count: %d\n",GetCSRCCount()); printf("CSRC count: %d\n",GetCSRCCount());
for (i = 0 ; i < GetCSRCCount() ; i++) for (i = 0 ; i < GetCSRCCount() ; i++)
printf(" CSRC[%02d]: 0x%08x\n",i,GetCSRC(i)); printf(" CSRC[%02d]: 0x%08x\n",i,GetCSRC(i));
printf("Payload: %s\n",GetPayloadData()); printf("Payload: %s\n",GetPayloadData());
printf("Payload length: %d\n",GetPayloadLength()); printf("Payload length: %d\n",GetPayloadLength());
printf("Packet length: %d\n",GetPacketLength()); printf("Packet length: %d\n",GetPacketLength());
printf("Extension: %s\n",HasExtension()?"yes":"no"); printf("Extension: %s\n",HasExtension()?"yes":"no");
if (HasExtension()) if (HasExtension())
{ {
printf(" Extension ID: 0x%04x\n",GetExtensionID()); printf(" Extension ID: 0x%04x\n",GetExtensionID());
printf(" Extension data: %s\n",GetExtensionData()); printf(" Extension data: %s\n",GetExtensionData());
printf(" Extension length: %d\n",GetExtensionLength()); printf(" Extension length: %d\n",GetExtensionLength());
} }
} }
#endif // RTPDEBUG #endif // RTPDEBUG

View File

@ -131,7 +131,7 @@ public:
/** Returns the payload length. */ /** Returns the payload length. */
size_t GetPayloadLength() const { return payloadlength; } size_t GetPayloadLength() const { return payloadlength; }
void SetPayloadLength(size_t l) { payloadlength = l; } void SetPayloadLength(size_t l) { payloadlength = l; }
/** If a header extension is present, this function returns the extension identifier. */ /** If a header extension is present, this function returns the extension identifier. */
uint16_t GetExtensionID() const { return extid; } uint16_t GetExtensionID() const { return extid; }

View File

@ -20,7 +20,7 @@ set (SPEEXDSP_SOURCES
) )
add_library(speexdsp ${SPEEXDSP_SOURCES}) add_library(speexdsp ${SPEEXDSP_SOURCES})
target_compile_definitions(speexdsp PUBLIC -DUSE_KISS_FFT -DFLOATING_POINT -DHAVE_STDINT_H) target_compile_definitions(speexdsp PUBLIC -DUSE_KISS_FFT -DFIXED_POINT -DHAVE_STDINT_H)
target_include_directories(speexdsp PUBLIC target_include_directories(speexdsp PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/libspeexdsp ${CMAKE_CURRENT_SOURCE_DIR}/libspeexdsp