Compare commits
No commits in common. "e342abe2f57646bcdb287a8dba23b9f200261639" and "c3c59ddf03b60a2a09657b7b0a5e2b85f0d51171" have entirely different histories.
e342abe2f5
...
c3c59ddf03
|
|
@ -184,3 +184,80 @@ void RtpDump::flush()
|
|||
}
|
||||
#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());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -72,4 +72,22 @@ public:
|
|||
};
|
||||
#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
|
||||
|
|
|
|||
|
|
@ -80,8 +80,6 @@ if (CMAKE_SYSTEM MATCHES "Windows*")
|
|||
endif()
|
||||
|
||||
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
|
||||
PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../../libs/
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ void JitterStatistics::process(jrtplib::RTPPacket* packet, int rate)
|
|||
Statistics::Statistics()
|
||||
:mReceived(0), mSent(0), mReceivedRtp(0), mSentRtp(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;
|
||||
memset(mLoss, 0, sizeof mLoss);
|
||||
|
|
@ -95,7 +95,7 @@ void Statistics::reset()
|
|||
mJitter = 0.0;
|
||||
mAudioTime = 0;
|
||||
mPacketDropped = 0;
|
||||
mDecodedAudio = 0;
|
||||
|
||||
memset(mLoss, 0, sizeof mLoss);
|
||||
}
|
||||
|
||||
|
|
@ -179,7 +179,7 @@ Statistics& Statistics::operator += (const Statistics& src)
|
|||
mPacketLoss += src.mPacketLoss;
|
||||
mPacketDropped += src.mPacketDropped;
|
||||
mAudioTime += src.mAudioTime;
|
||||
mDecodedAudio += src.mDecodedAudio;
|
||||
|
||||
|
||||
for (auto codecStat: src.mCodecCount)
|
||||
{
|
||||
|
|
@ -230,7 +230,6 @@ Statistics& Statistics::operator -= (const Statistics& src)
|
|||
mOldRtp -= src.mOldRtp;
|
||||
mPacketLoss -= src.mPacketLoss;
|
||||
mPacketDropped -= src.mPacketDropped;
|
||||
mDecodedAudio -= src.mDecodedAudio;
|
||||
|
||||
mAudioTime -= src.mAudioTime;
|
||||
for (auto codecStat: src.mCodecCount)
|
||||
|
|
|
|||
|
|
@ -63,8 +63,6 @@ public:
|
|||
mPacketDropped, // Number of dropped packets (due to time unsync when playing)б
|
||||
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
|
||||
mDecodeRequested, // Average amount of requested audio frames to play
|
||||
mPacketInterval; // Average interval between packet adding to jitter buffer
|
||||
|
|
@ -100,10 +98,10 @@ public:
|
|||
Statistics& operator -= (const Statistics& src);
|
||||
|
||||
float mNetworkMos = 0.0;
|
||||
// #if defined(USE_PVQA_LIBRARY) && !defined(PVQA_SERVER)
|
||||
// float mPvqaMos = 0.0;
|
||||
//std::string mPvqaReport;
|
||||
// #endif
|
||||
#if defined(USE_PVQA_LIBRARY) && !defined(PVQA_SERVER)
|
||||
float mPvqaMos = 0.0;
|
||||
std::string mPvqaReport;
|
||||
#endif
|
||||
|
||||
std::string toString() const;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -201,6 +201,7 @@ void Logger::beginLine(LogLevel level, const char* filename, int linenumber, con
|
|||
void
|
||||
Logger::endLine()
|
||||
{
|
||||
*mStream << std::endl;
|
||||
*mStream << std::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)
|
||||
<< 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();
|
||||
if (mUseDebugWindow) {
|
||||
|
|
|
|||
|
|
@ -86,14 +86,8 @@ protected:
|
|||
class LogLock
|
||||
{
|
||||
public:
|
||||
LogLock(LogGuard& g) :mGuard(g)
|
||||
{
|
||||
mGuard.Lock();
|
||||
}
|
||||
~LogLock()
|
||||
{
|
||||
mGuard.Unlock();
|
||||
}
|
||||
LogLock(LogGuard& g) :mGuard(g) { mGuard.Lock(); }
|
||||
~LogLock() { mGuard.Unlock(); }
|
||||
|
||||
protected:
|
||||
LogGuard& mGuard;
|
||||
|
|
|
|||
|
|
@ -91,4 +91,4 @@ set(JRTPLIB_SOURCES
|
|||
rtpexternaltransmitter.cpp)
|
||||
|
||||
add_library(jrtplib STATIC ${JRTPLIB_SOURCES})
|
||||
target_include_directories(jrtplib PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
||||
|
|
|
|||
|
|
@ -53,56 +53,56 @@ class RTCPPacket;
|
|||
class JRTPLIB_IMPORTEXPORT RTCPCompoundPacket : public RTPMemoryObject
|
||||
{
|
||||
public:
|
||||
/** Creates an RTCPCompoundPacket instance from the data in \c rawpack, installing a memory manager if specified. */
|
||||
RTCPCompoundPacket(RTPRawPacket &rawpack, RTPMemoryManager *memmgr = 0);
|
||||
/** Creates an RTCPCompoundPacket instance from the data in \c rawpack, installing a memory manager if specified. */
|
||||
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. 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, size_t len, bool deletedata = true, 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. 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, size_t len, bool deletedata = true, RTPMemoryManager *memmgr = 0);
|
||||
protected:
|
||||
RTCPCompoundPacket(RTPMemoryManager *memmgr); // this is for the compoundpacket builder
|
||||
RTCPCompoundPacket(RTPMemoryManager *memmgr); // this is for the compoundpacket builder
|
||||
public:
|
||||
virtual ~RTCPCompoundPacket();
|
||||
virtual ~RTCPCompoundPacket();
|
||||
|
||||
/** 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
|
||||
* what went wrong. If the packet had an invalid format, the return value is \c ERR_RTP_RTCPCOMPOUND_INVALIDPACKET.
|
||||
*/
|
||||
int GetCreationError() { return error; }
|
||||
/** 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
|
||||
* what went wrong. If the packet had an invalid format, the return value is \c ERR_RTP_RTCPCOMPOUND_INVALIDPACKET.
|
||||
*/
|
||||
int GetCreationError() { return error; }
|
||||
|
||||
/** Returns a pointer to the data of the entire RTCP compound packet. */
|
||||
const uint8_t *GetCompoundPacketData() { return compoundpacket; }
|
||||
/** Returns a pointer to the data of the entire RTCP compound packet. */
|
||||
const uint8_t *GetCompoundPacketData() { return compoundpacket; }
|
||||
|
||||
/** Returns the size of the entire RTCP compound packet. */
|
||||
size_t GetCompoundPacketLength() { return compoundpacketlength; }
|
||||
/** Returns the size of the entire RTCP compound packet. */
|
||||
size_t GetCompoundPacketLength() { return compoundpacketlength; }
|
||||
|
||||
/** Starts the iteration over the individual RTCP packets in the RTCP compound packet. */
|
||||
void GotoFirstPacket() { rtcppackit = rtcppacklist.begin(); }
|
||||
/** Starts the iteration over the individual RTCP packets in the RTCP compound packet. */
|
||||
void GotoFirstPacket() { rtcppackit = rtcppacklist.begin(); }
|
||||
|
||||
/** 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
|
||||
* on the RTCPPacket instance which is returned.
|
||||
*/
|
||||
RTCPPacket *GetNextPacket() { if (rtcppackit == rtcppacklist.end()) return 0; RTCPPacket *p = *rtcppackit; rtcppackit++; return p; }
|
||||
/** 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
|
||||
* on the RTCPPacket instance which is returned.
|
||||
*/
|
||||
RTCPPacket *GetNextPacket() { if (rtcppackit == rtcppacklist.end()) return 0; RTCPPacket *p = *rtcppackit; rtcppackit++; return p; }
|
||||
|
||||
#ifdef RTPDEBUG
|
||||
void Dump();
|
||||
void Dump();
|
||||
#endif // RTPDEBUG
|
||||
protected:
|
||||
void ClearPacketList();
|
||||
int ParseData(uint8_t *packet, size_t len);
|
||||
void ClearPacketList();
|
||||
int ParseData(uint8_t *packet, size_t len);
|
||||
|
||||
int error;
|
||||
int error;
|
||||
|
||||
const uint8_t *compoundpacket;
|
||||
size_t compoundpacketlength;
|
||||
bool deletepacket;
|
||||
const uint8_t *compoundpacket;
|
||||
size_t compoundpacketlength;
|
||||
bool deletepacket;
|
||||
|
||||
std::list<RTCPPacket *> rtcppacklist;
|
||||
std::list<RTCPPacket *>::const_iterator rtcppackit;
|
||||
std::list<RTCPPacket *> rtcppacklist;
|
||||
std::list<RTCPPacket *>::const_iterator rtcppackit;
|
||||
};
|
||||
|
||||
} // end namespace
|
||||
|
|
|
|||
|
|
@ -36,12 +36,12 @@
|
|||
#include "rtperrors.h"
|
||||
#include "rtprawpacket.h"
|
||||
#if ! (defined(WIN32) || defined(_WIN32_WCE))
|
||||
#include <netinet/in.h>
|
||||
#include <string.h>
|
||||
#include <netinet/in.h>
|
||||
#include <string.h>
|
||||
#endif // WIN32
|
||||
|
||||
#ifdef RTPDEBUG
|
||||
#include <stdio.h>
|
||||
#include <stdio.h>
|
||||
#endif // RTPDEBUG
|
||||
|
||||
#include "rtpdebug.h"
|
||||
|
|
@ -51,310 +51,306 @@ namespace jrtplib
|
|||
|
||||
void RTPPacket::Clear()
|
||||
{
|
||||
hasextension = false;
|
||||
hasmarker = false;
|
||||
numcsrcs = 0;
|
||||
payloadtype = 0;
|
||||
extseqnr = 0;
|
||||
timestamp = 0;
|
||||
ssrc = 0;
|
||||
packet = 0;
|
||||
payload = 0;
|
||||
packetlength = 0;
|
||||
payloadlength = 0;
|
||||
extid = 0;
|
||||
extension = 0;
|
||||
extensionlength = 0;
|
||||
error = 0;
|
||||
externalbuffer = false;
|
||||
hasextension = false;
|
||||
hasmarker = false;
|
||||
numcsrcs = 0;
|
||||
payloadtype = 0;
|
||||
extseqnr = 0;
|
||||
timestamp = 0;
|
||||
ssrc = 0;
|
||||
packet = 0;
|
||||
payload = 0;
|
||||
packetlength = 0;
|
||||
payloadlength = 0;
|
||||
extid = 0;
|
||||
extension = 0;
|
||||
extensionlength = 0;
|
||||
error = 0;
|
||||
externalbuffer = false;
|
||||
}
|
||||
|
||||
RTPPacket::RTPPacket(RTPRawPacket &rawpack,RTPMemoryManager *mgr) : RTPMemoryObject(mgr),receivetime(rawpack.GetReceiveTime())
|
||||
{
|
||||
Clear();
|
||||
error = ParseRawPacket(rawpack);
|
||||
Clear();
|
||||
error = ParseRawPacket(rawpack);
|
||||
}
|
||||
|
||||
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,
|
||||
bool gotextension,uint16_t extensionid,uint16_t extensionlen_numwords,const void *extensiondata,
|
||||
size_t maxpacksize, RTPMemoryManager *mgr) : RTPMemoryObject(mgr),receivetime(0,0)
|
||||
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,
|
||||
size_t maxpacksize, RTPMemoryManager *mgr) : RTPMemoryObject(mgr),receivetime(0,0)
|
||||
{
|
||||
Clear();
|
||||
error = BuildPacket(payloadtype,payloaddata,payloadlen,seqnr,timestamp,ssrc,gotmarker,numcsrcs,
|
||||
csrcs,gotextension,extensionid,extensionlen_numwords,extensiondata,0,maxpacksize);
|
||||
Clear();
|
||||
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,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,size_t buffersize, RTPMemoryManager *mgr) : RTPMemoryObject(mgr),receivetime(0,0)
|
||||
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,size_t buffersize, RTPMemoryManager *mgr) : RTPMemoryObject(mgr),receivetime(0,0)
|
||||
{
|
||||
Clear();
|
||||
if (buffer == 0)
|
||||
error = ERR_RTP_PACKET_EXTERNALBUFFERNULL;
|
||||
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);
|
||||
Clear();
|
||||
if (buffer == 0)
|
||||
error = ERR_RTP_PACKET_EXTERNALBUFFERNULL;
|
||||
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);
|
||||
}
|
||||
|
||||
RTPPacket::~RTPPacket()
|
||||
{
|
||||
if (packet && !externalbuffer)
|
||||
{
|
||||
RTPDeleteByteArray(packet,GetMemoryManager());
|
||||
}
|
||||
if (packet && !externalbuffer)
|
||||
{
|
||||
RTPDeleteByteArray(packet,GetMemoryManager());
|
||||
}
|
||||
}
|
||||
|
||||
int RTPPacket::ParseRawPacket(RTPRawPacket &rawpack)
|
||||
{
|
||||
uint8_t *packetbytes;
|
||||
size_t packetlen;
|
||||
uint8_t payloadtype;
|
||||
RTPHeader *rtpheader;
|
||||
bool marker;
|
||||
int csrccount;
|
||||
bool hasextension;
|
||||
int payloadoffset,payloadlength;
|
||||
int numpadbytes;
|
||||
RTPExtensionHeader *rtpextheader;
|
||||
uint16_t exthdrlen;
|
||||
uint8_t *packetbytes;
|
||||
size_t packetlen;
|
||||
uint8_t payloadtype;
|
||||
RTPHeader *rtpheader;
|
||||
bool marker;
|
||||
int csrccount;
|
||||
bool hasextension;
|
||||
int payloadoffset,payloadlength;
|
||||
int numpadbytes;
|
||||
RTPExtensionHeader *rtpextheader;
|
||||
uint16_t exthdrlen;
|
||||
|
||||
if (!rawpack.IsRTP()) // If we didn't receive it on the RTP port, we'll ignore it
|
||||
return ERR_RTP_PACKET_INVALIDPACKET;
|
||||
if (!rawpack.IsRTP()) // If we didn't receive it on the RTP port, we'll ignore it
|
||||
return ERR_RTP_PACKET_INVALIDPACKET;
|
||||
|
||||
// The length should be at least the size of the RTP header
|
||||
packetlen = rawpack.GetDataLength();
|
||||
if (packetlen < sizeof(RTPHeader))
|
||||
return ERR_RTP_PACKET_INVALIDPACKET;
|
||||
// The length should be at least the size of the RTP header
|
||||
packetlen = rawpack.GetDataLength();
|
||||
if (packetlen < sizeof(RTPHeader))
|
||||
return ERR_RTP_PACKET_INVALIDPACKET;
|
||||
|
||||
packetbytes = (uint8_t *)rawpack.GetData();
|
||||
rtpheader = (RTPHeader *)packetbytes;
|
||||
packetbytes = (uint8_t *)rawpack.GetData();
|
||||
rtpheader = (RTPHeader *)packetbytes;
|
||||
|
||||
// The version number should be correct
|
||||
if (rtpheader->version != RTP_VERSION)
|
||||
return ERR_RTP_PACKET_INVALIDPACKET;
|
||||
// The version number should be correct
|
||||
if (rtpheader->version != RTP_VERSION)
|
||||
return ERR_RTP_PACKET_INVALIDPACKET;
|
||||
|
||||
// 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
|
||||
// identifier
|
||||
marker = (rtpheader->marker == 0)?false:true;
|
||||
payloadtype = rtpheader->payloadtype;
|
||||
if (marker)
|
||||
{
|
||||
if (payloadtype == (RTP_RTCPTYPE_SR & 127)) // don't check high bit (this was the marker!!)
|
||||
return ERR_RTP_PACKET_INVALIDPACKET;
|
||||
if (payloadtype == (RTP_RTCPTYPE_RR & 127))
|
||||
return ERR_RTP_PACKET_INVALIDPACKET;
|
||||
}
|
||||
// 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
|
||||
// identifier
|
||||
marker = (rtpheader->marker == 0)?false:true;
|
||||
payloadtype = rtpheader->payloadtype;
|
||||
if (marker)
|
||||
{
|
||||
if (payloadtype == (RTP_RTCPTYPE_SR & 127)) // don't check high bit (this was the marker!!)
|
||||
return ERR_RTP_PACKET_INVALIDPACKET;
|
||||
if (payloadtype == (RTP_RTCPTYPE_RR & 127))
|
||||
return ERR_RTP_PACKET_INVALIDPACKET;
|
||||
}
|
||||
|
||||
csrccount = rtpheader->csrccount;
|
||||
payloadoffset = sizeof(RTPHeader)+(int)(csrccount*sizeof(uint32_t));
|
||||
if ((size_t)payloadoffset > packetlen)
|
||||
return ERR_RTP_PACKET_INVALIDPACKET;
|
||||
csrccount = rtpheader->csrccount;
|
||||
payloadoffset = sizeof(RTPHeader)+(int)(csrccount*sizeof(uint32_t));
|
||||
|
||||
if (rtpheader->padding) // adjust payload length to take padding into account
|
||||
{
|
||||
numpadbytes = (int)packetbytes[packetlen-1]; // last byte contains number of padding bytes
|
||||
if (numpadbytes <= 0)
|
||||
return ERR_RTP_PACKET_INVALIDPACKET;
|
||||
}
|
||||
else
|
||||
numpadbytes = 0;
|
||||
if (rtpheader->padding) // adjust payload length to take padding into account
|
||||
{
|
||||
numpadbytes = (int)packetbytes[packetlen-1]; // last byte contains number of padding bytes
|
||||
if (numpadbytes <= 0)
|
||||
return ERR_RTP_PACKET_INVALIDPACKET;
|
||||
}
|
||||
else
|
||||
numpadbytes = 0;
|
||||
|
||||
hasextension = (rtpheader->extension == 0)?false:true;
|
||||
if (hasextension) // got header extension
|
||||
{
|
||||
rtpextheader = (RTPExtensionHeader *)(packetbytes+payloadoffset);
|
||||
payloadoffset += sizeof(RTPExtensionHeader);
|
||||
if ((size_t)payloadoffset > packetlen)
|
||||
return ERR_RTP_PACKET_INVALIDPACKET;
|
||||
exthdrlen = ntohs(rtpextheader->length);
|
||||
payloadoffset += ((int)exthdrlen)*sizeof(uint32_t);
|
||||
}
|
||||
else
|
||||
{
|
||||
rtpextheader = 0;
|
||||
exthdrlen = 0;
|
||||
}
|
||||
hasextension = (rtpheader->extension == 0)?false:true;
|
||||
if (hasextension) // got header extension
|
||||
{
|
||||
rtpextheader = (RTPExtensionHeader *)(packetbytes+payloadoffset);
|
||||
payloadoffset += sizeof(RTPExtensionHeader);
|
||||
exthdrlen = ntohs(rtpextheader->length);
|
||||
payloadoffset += ((int)exthdrlen)*sizeof(uint32_t);
|
||||
}
|
||||
else
|
||||
{
|
||||
rtpextheader = 0;
|
||||
exthdrlen = 0;
|
||||
}
|
||||
|
||||
payloadlength = packetlen-numpadbytes-payloadoffset;
|
||||
if (payloadlength < 0)
|
||||
return ERR_RTP_PACKET_INVALIDPACKET;
|
||||
payloadlength = packetlen-numpadbytes-payloadoffset;
|
||||
if (payloadlength < 0)
|
||||
return ERR_RTP_PACKET_INVALIDPACKET;
|
||||
|
||||
// Now, we've got a valid packet, so we can create a new instance of RTPPacket
|
||||
// and fill in the members
|
||||
// Now, we've got a valid packet, so we can create a new instance of RTPPacket
|
||||
// and fill in the members
|
||||
|
||||
RTPPacket::hasextension = hasextension;
|
||||
if (hasextension)
|
||||
{
|
||||
RTPPacket::extid = ntohs(rtpextheader->extid);
|
||||
RTPPacket::extensionlength = ((int)ntohs(rtpextheader->length))*sizeof(uint32_t);
|
||||
RTPPacket::extension = ((uint8_t *)rtpextheader)+sizeof(RTPExtensionHeader);
|
||||
}
|
||||
RTPPacket::hasextension = hasextension;
|
||||
if (hasextension)
|
||||
{
|
||||
RTPPacket::extid = ntohs(rtpextheader->extid);
|
||||
RTPPacket::extensionlength = ((int)ntohs(rtpextheader->length))*sizeof(uint32_t);
|
||||
RTPPacket::extension = ((uint8_t *)rtpextheader)+sizeof(RTPExtensionHeader);
|
||||
}
|
||||
|
||||
RTPPacket::hasmarker = marker;
|
||||
RTPPacket::numcsrcs = csrccount;
|
||||
RTPPacket::payloadtype = payloadtype;
|
||||
RTPPacket::hasmarker = marker;
|
||||
RTPPacket::numcsrcs = csrccount;
|
||||
RTPPacket::payloadtype = payloadtype;
|
||||
|
||||
// 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
|
||||
// 16 bits
|
||||
RTPPacket::extseqnr = (uint32_t)ntohs(rtpheader->sequencenumber);
|
||||
// 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
|
||||
// 16 bits
|
||||
RTPPacket::extseqnr = (uint32_t)ntohs(rtpheader->sequencenumber);
|
||||
|
||||
RTPPacket::timestamp = ntohl(rtpheader->timestamp);
|
||||
RTPPacket::ssrc = ntohl(rtpheader->ssrc);
|
||||
RTPPacket::packet = packetbytes;
|
||||
RTPPacket::payload = packetbytes+payloadoffset;
|
||||
RTPPacket::packetlength = packetlen;
|
||||
RTPPacket::payloadlength = payloadlength;
|
||||
RTPPacket::timestamp = ntohl(rtpheader->timestamp);
|
||||
RTPPacket::ssrc = ntohl(rtpheader->ssrc);
|
||||
RTPPacket::packet = packetbytes;
|
||||
RTPPacket::payload = packetbytes+payloadoffset;
|
||||
RTPPacket::packetlength = packetlen;
|
||||
RTPPacket::payloadlength = payloadlength;
|
||||
|
||||
// We'll zero the data of the raw packet, since we're using it here now!
|
||||
rawpack.ZeroData();
|
||||
// We'll zero the data of the raw packet, since we're using it here now!
|
||||
rawpack.ZeroData();
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t RTPPacket::GetCSRC(int num) const
|
||||
{
|
||||
if (num >= numcsrcs)
|
||||
return 0;
|
||||
if (num >= numcsrcs)
|
||||
return 0;
|
||||
|
||||
uint8_t *csrcpos;
|
||||
uint32_t *csrcval_nbo;
|
||||
uint32_t csrcval_hbo;
|
||||
uint8_t *csrcpos;
|
||||
uint32_t *csrcval_nbo;
|
||||
uint32_t csrcval_hbo;
|
||||
|
||||
csrcpos = packet+sizeof(RTPHeader)+num*sizeof(uint32_t);
|
||||
csrcval_nbo = (uint32_t *)csrcpos;
|
||||
csrcval_hbo = ntohl(*csrcval_nbo);
|
||||
return csrcval_hbo;
|
||||
csrcpos = packet+sizeof(RTPHeader)+num*sizeof(uint32_t);
|
||||
csrcval_nbo = (uint32_t *)csrcpos;
|
||||
csrcval_hbo = ntohl(*csrcval_nbo);
|
||||
return csrcval_hbo;
|
||||
}
|
||||
|
||||
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,
|
||||
bool gotextension,uint16_t extensionid,uint16_t extensionlen_numwords,const void *extensiondata,
|
||||
void *buffer,size_t maxsize)
|
||||
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,size_t maxsize)
|
||||
{
|
||||
if (numcsrcs > RTP_MAXCSRCS)
|
||||
return ERR_RTP_PACKET_TOOMANYCSRCS;
|
||||
if (numcsrcs > RTP_MAXCSRCS)
|
||||
return ERR_RTP_PACKET_TOOMANYCSRCS;
|
||||
|
||||
if (payloadtype > 127) // high bit should not be used
|
||||
return ERR_RTP_PACKET_BADPAYLOADTYPE;
|
||||
if (payloadtype == 72 || payloadtype == 73) // could cause confusion with rtcp types
|
||||
return ERR_RTP_PACKET_BADPAYLOADTYPE;
|
||||
if (payloadtype > 127) // high bit should not be used
|
||||
return ERR_RTP_PACKET_BADPAYLOADTYPE;
|
||||
if (payloadtype == 72 || payloadtype == 73) // could cause confusion with rtcp types
|
||||
return ERR_RTP_PACKET_BADPAYLOADTYPE;
|
||||
|
||||
packetlength = sizeof(RTPHeader);
|
||||
packetlength += sizeof(uint32_t)*((size_t)numcsrcs);
|
||||
if (gotextension)
|
||||
{
|
||||
packetlength += sizeof(RTPExtensionHeader);
|
||||
packetlength += sizeof(uint32_t)*((size_t)extensionlen_numwords);
|
||||
}
|
||||
packetlength += payloadlen;
|
||||
packetlength = sizeof(RTPHeader);
|
||||
packetlength += sizeof(uint32_t)*((size_t)numcsrcs);
|
||||
if (gotextension)
|
||||
{
|
||||
packetlength += sizeof(RTPExtensionHeader);
|
||||
packetlength += sizeof(uint32_t)*((size_t)extensionlen_numwords);
|
||||
}
|
||||
packetlength += payloadlen;
|
||||
|
||||
if (maxsize > 0 && packetlength > maxsize)
|
||||
{
|
||||
packetlength = 0;
|
||||
return ERR_RTP_PACKET_DATAEXCEEDSMAXSIZE;
|
||||
}
|
||||
if (maxsize > 0 && packetlength > maxsize)
|
||||
{
|
||||
packetlength = 0;
|
||||
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)
|
||||
{
|
||||
packet = RTPNew(GetMemoryManager(),RTPMEM_TYPE_BUFFER_RTPPACKET) uint8_t [packetlength];
|
||||
if (packet == 0)
|
||||
{
|
||||
packetlength = 0;
|
||||
return ERR_RTP_OUTOFMEM;
|
||||
}
|
||||
externalbuffer = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
packet = (uint8_t *)buffer;
|
||||
externalbuffer = true;
|
||||
}
|
||||
if (buffer == 0)
|
||||
{
|
||||
packet = RTPNew(GetMemoryManager(),RTPMEM_TYPE_BUFFER_RTPPACKET) uint8_t [packetlength];
|
||||
if (packet == 0)
|
||||
{
|
||||
packetlength = 0;
|
||||
return ERR_RTP_OUTOFMEM;
|
||||
}
|
||||
externalbuffer = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
packet = (uint8_t *)buffer;
|
||||
externalbuffer = true;
|
||||
}
|
||||
|
||||
RTPPacket::hasmarker = gotmarker;
|
||||
RTPPacket::hasextension = gotextension;
|
||||
RTPPacket::numcsrcs = numcsrcs;
|
||||
RTPPacket::payloadtype = payloadtype;
|
||||
RTPPacket::extseqnr = (uint32_t)seqnr;
|
||||
RTPPacket::timestamp = timestamp;
|
||||
RTPPacket::ssrc = ssrc;
|
||||
RTPPacket::payloadlength = payloadlen;
|
||||
RTPPacket::extid = extensionid;
|
||||
RTPPacket::extensionlength = ((size_t)extensionlen_numwords)*sizeof(uint32_t);
|
||||
RTPPacket::hasmarker = gotmarker;
|
||||
RTPPacket::hasextension = gotextension;
|
||||
RTPPacket::numcsrcs = numcsrcs;
|
||||
RTPPacket::payloadtype = payloadtype;
|
||||
RTPPacket::extseqnr = (uint32_t)seqnr;
|
||||
RTPPacket::timestamp = timestamp;
|
||||
RTPPacket::ssrc = ssrc;
|
||||
RTPPacket::payloadlength = payloadlen;
|
||||
RTPPacket::extid = extensionid;
|
||||
RTPPacket::extensionlength = ((size_t)extensionlen_numwords)*sizeof(uint32_t);
|
||||
|
||||
rtphdr = (RTPHeader *)packet;
|
||||
rtphdr->version = RTP_VERSION;
|
||||
rtphdr->padding = 0;
|
||||
if (gotmarker)
|
||||
rtphdr->marker = 1;
|
||||
else
|
||||
rtphdr->marker = 0;
|
||||
if (gotextension)
|
||||
rtphdr->extension = 1;
|
||||
else
|
||||
rtphdr->extension = 0;
|
||||
rtphdr->csrccount = numcsrcs;
|
||||
rtphdr->payloadtype = payloadtype&127; // make sure high bit isn't set
|
||||
rtphdr->sequencenumber = htons(seqnr);
|
||||
rtphdr->timestamp = htonl(timestamp);
|
||||
rtphdr->ssrc = htonl(ssrc);
|
||||
rtphdr = (RTPHeader *)packet;
|
||||
rtphdr->version = RTP_VERSION;
|
||||
rtphdr->padding = 0;
|
||||
if (gotmarker)
|
||||
rtphdr->marker = 1;
|
||||
else
|
||||
rtphdr->marker = 0;
|
||||
if (gotextension)
|
||||
rtphdr->extension = 1;
|
||||
else
|
||||
rtphdr->extension = 0;
|
||||
rtphdr->csrccount = numcsrcs;
|
||||
rtphdr->payloadtype = payloadtype&127; // make sure high bit isn't set
|
||||
rtphdr->sequencenumber = htons(seqnr);
|
||||
rtphdr->timestamp = htonl(timestamp);
|
||||
rtphdr->ssrc = htonl(ssrc);
|
||||
|
||||
uint32_t *curcsrc;
|
||||
int i;
|
||||
uint32_t *curcsrc;
|
||||
int i;
|
||||
|
||||
curcsrc = (uint32_t *)(packet+sizeof(RTPHeader));
|
||||
for (i = 0 ; i < numcsrcs ; i++,curcsrc++)
|
||||
*curcsrc = htonl(csrcs[i]);
|
||||
curcsrc = (uint32_t *)(packet+sizeof(RTPHeader));
|
||||
for (i = 0 ; i < numcsrcs ; i++,curcsrc++)
|
||||
*curcsrc = htonl(csrcs[i]);
|
||||
|
||||
payload = packet+sizeof(RTPHeader)+((size_t)numcsrcs)*sizeof(uint32_t);
|
||||
if (gotextension)
|
||||
{
|
||||
RTPExtensionHeader *rtpexthdr = (RTPExtensionHeader *)payload;
|
||||
payload = packet+sizeof(RTPHeader)+((size_t)numcsrcs)*sizeof(uint32_t);
|
||||
if (gotextension)
|
||||
{
|
||||
RTPExtensionHeader *rtpexthdr = (RTPExtensionHeader *)payload;
|
||||
|
||||
rtpexthdr->extid = htons(extensionid);
|
||||
rtpexthdr->length = htons((uint16_t)extensionlen_numwords);
|
||||
rtpexthdr->extid = htons(extensionid);
|
||||
rtpexthdr->length = htons((uint16_t)extensionlen_numwords);
|
||||
|
||||
payload += sizeof(RTPExtensionHeader);
|
||||
memcpy(payload,extensiondata,RTPPacket::extensionlength);
|
||||
payload += sizeof(RTPExtensionHeader);
|
||||
memcpy(payload,extensiondata,RTPPacket::extensionlength);
|
||||
|
||||
payload += RTPPacket::extensionlength;
|
||||
}
|
||||
memcpy(payload,payloaddata,payloadlen);
|
||||
return 0;
|
||||
payload += RTPPacket::extensionlength;
|
||||
}
|
||||
memcpy(payload,payloaddata,payloadlen);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef RTPDEBUG
|
||||
void RTPPacket::Dump()
|
||||
{
|
||||
int i;
|
||||
int i;
|
||||
|
||||
printf("Payload type: %d\n",(int)GetPayloadType());
|
||||
printf("Extended sequence number: 0x%08x\n",GetExtendedSequenceNumber());
|
||||
printf("Timestamp: 0x%08x\n",GetTimestamp());
|
||||
printf("SSRC: 0x%08x\n",GetSSRC());
|
||||
printf("Marker: %s\n",HasMarker()?"yes":"no");
|
||||
printf("CSRC count: %d\n",GetCSRCCount());
|
||||
for (i = 0 ; i < GetCSRCCount() ; i++)
|
||||
printf(" CSRC[%02d]: 0x%08x\n",i,GetCSRC(i));
|
||||
printf("Payload: %s\n",GetPayloadData());
|
||||
printf("Payload length: %d\n",GetPayloadLength());
|
||||
printf("Packet length: %d\n",GetPacketLength());
|
||||
printf("Extension: %s\n",HasExtension()?"yes":"no");
|
||||
if (HasExtension())
|
||||
{
|
||||
printf(" Extension ID: 0x%04x\n",GetExtensionID());
|
||||
printf(" Extension data: %s\n",GetExtensionData());
|
||||
printf(" Extension length: %d\n",GetExtensionLength());
|
||||
}
|
||||
printf("Payload type: %d\n",(int)GetPayloadType());
|
||||
printf("Extended sequence number: 0x%08x\n",GetExtendedSequenceNumber());
|
||||
printf("Timestamp: 0x%08x\n",GetTimestamp());
|
||||
printf("SSRC: 0x%08x\n",GetSSRC());
|
||||
printf("Marker: %s\n",HasMarker()?"yes":"no");
|
||||
printf("CSRC count: %d\n",GetCSRCCount());
|
||||
for (i = 0 ; i < GetCSRCCount() ; i++)
|
||||
printf(" CSRC[%02d]: 0x%08x\n",i,GetCSRC(i));
|
||||
printf("Payload: %s\n",GetPayloadData());
|
||||
printf("Payload length: %d\n",GetPayloadLength());
|
||||
printf("Packet length: %d\n",GetPacketLength());
|
||||
printf("Extension: %s\n",HasExtension()?"yes":"no");
|
||||
if (HasExtension())
|
||||
{
|
||||
printf(" Extension ID: 0x%04x\n",GetExtensionID());
|
||||
printf(" Extension data: %s\n",GetExtensionData());
|
||||
printf(" Extension length: %d\n",GetExtensionLength());
|
||||
}
|
||||
}
|
||||
#endif // RTPDEBUG
|
||||
|
||||
|
|
|
|||
|
|
@ -131,7 +131,7 @@ public:
|
|||
|
||||
/** Returns the payload length. */
|
||||
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. */
|
||||
uint16_t GetExtensionID() const { return extid; }
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ set (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
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/libspeexdsp
|
||||
|
|
|
|||
Loading…
Reference in New Issue