- better internal statistics + memory performance optimization

This commit is contained in:
2026-06-18 12:28:19 +03:00
parent 2cb2a93d59
commit 1e020a7b5f
9 changed files with 83 additions and 56 deletions
+10 -7
View File
@@ -18,9 +18,7 @@ namespace Audio
SpeexResampler::SpeexResampler() SpeexResampler::SpeexResampler()
:mContext(NULL), mErrorCode(0), mSourceRate(0), mDestRate(0), mLastSample(0), mChannels(0) {}
{
}
void SpeexResampler::start(int channels, int sourceRate, int destRate) void SpeexResampler::start(int channels, int sourceRate, int destRate)
{ {
@@ -51,6 +49,11 @@ void SpeexResampler::stop()
} }
} }
bool SpeexResampler::isOpened() const
{
return mContext != nullptr;
}
SpeexResampler::~SpeexResampler() SpeexResampler::~SpeexResampler()
{ {
stop(); stop();
@@ -113,22 +116,22 @@ size_t SpeexResampler::processBuffer(const void* src, size_t sourceLength, size_
return outLen * sizeof(short) * mChannels; return outLen * sizeof(short) * mChannels;
} }
int SpeexResampler::sourceRate() int SpeexResampler::sourceRate() const
{ {
return mSourceRate; return mSourceRate;
} }
int SpeexResampler::destRate() int SpeexResampler::destRate() const
{ {
return mDestRate; return mDestRate;
} }
size_t SpeexResampler::getDestLength(size_t sourceLen) size_t SpeexResampler::getDestLength(size_t sourceLen) const
{ {
return size_t(sourceLen * (float(mDestRate) / mSourceRate) + 0.5f); return size_t(sourceLen * (float(mDestRate) / mSourceRate) + 0.5f);
} }
size_t SpeexResampler::getSourceLength(size_t destLen) size_t SpeexResampler::getSourceLength(size_t destLen) const
{ {
// Here we want to get 'destLen' number of samples // Here we want to get 'destLen' number of samples
return size_t(destLen * (float(mSourceRate) / mDestRate) + 0.5f); return size_t(destLen * (float(mSourceRate) / mDestRate) + 0.5f);
+12 -10
View File
@@ -24,23 +24,25 @@ namespace Audio
void start(int channels, int sourceRate, int destRate); void start(int channels, int sourceRate, int destRate);
void stop(); void stop();
bool isOpened() const;
size_t processBuffer(const void* source, size_t sourceLength, size_t& sourceProcessed, size_t processBuffer(const void* source, size_t sourceLength, size_t& sourceProcessed,
void* dest, size_t destCapacity); void* dest, size_t destCapacity);
int sourceRate(); int sourceRate() const;
int destRate(); int destRate() const;
size_t getDestLength(size_t sourceLen); size_t getDestLength(size_t sourceLen) const;
size_t getSourceLength(size_t destLen); size_t getSourceLength(size_t destLen) const;
// Returns instance + speex encoder size in bytes // Returns instance + speex encoder size in bytes
size_t getSize() const; size_t getSize() const;
protected: protected:
void* mContext; void* mContext = nullptr;
int mErrorCode; int mErrorCode = 0;
int mSourceRate, int mSourceRate = 0,
mDestRate, mDestRate = 0,
mChannels; mChannels = 0;
short mLastSample; short mLastSample = 0;
}; };
typedef SpeexResampler Resampler; typedef SpeexResampler Resampler;
+13 -10
View File
@@ -368,20 +368,10 @@ Receiver::~Receiver()
AudioReceiver::AudioReceiver(const CodecList::Settings& settings, MT::Statistics &stat) AudioReceiver::AudioReceiver(const CodecList::Settings& settings, MT::Statistics &stat)
:Receiver(stat), mRtpBuffer(stat), mDtmfBuffer(stat), mCodecSettings(settings), mCodecList(settings), mDtmfReceiver(stat) :Receiver(stat), mRtpBuffer(stat), mDtmfBuffer(stat), mCodecSettings(settings), mCodecList(settings), mDtmfReceiver(stat)
{ {
// Init resamplers
mResampler8.start(AUDIO_CHANNELS, 8000, AUDIO_SAMPLERATE);
mResampler16.start(AUDIO_CHANNELS, 16000, AUDIO_SAMPLERATE);
mResampler32.start(AUDIO_CHANNELS, 32000, AUDIO_SAMPLERATE);
mResampler48.start(AUDIO_CHANNELS, 48000, AUDIO_SAMPLERATE);
// Init codecs // Init codecs
mCodecList.setSettings(settings); mCodecList.setSettings(settings);
mCodecList.fillCodecMap(mCodecMap); mCodecList.fillCodecMap(mCodecMap);
// 10 seconds is the maximum length of decoded audio in single step
// It is important - DTX may produce silence up to few seconds easily
mAvailable.setCapacity(AUDIO_SAMPLERATE * 10 * sizeof(short));
mDtmfBuffer.setPrebuffer(0ms); mDtmfBuffer.setPrebuffer(0ms);
mDtmfBuffer.setLow(0ms); mDtmfBuffer.setLow(0ms);
mDtmfBuffer.setHigh(1ms); mDtmfBuffer.setHigh(1ms);
@@ -389,6 +379,12 @@ AudioReceiver::AudioReceiver(const CodecList::Settings& settings, MT::Statistics
// Avoid collecting too much data // Avoid collecting too much data
mRtpBuffer.setHigh(240ms); mRtpBuffer.setHigh(240ms);
// Resamplers are lazy inside; there is no actual memory allocation
mResampler8.start(AUDIO_CHANNELS, 8000, AUDIO_SAMPLERATE);
mResampler16.start(AUDIO_CHANNELS, 16000, AUDIO_SAMPLERATE);
mResampler32.start(AUDIO_CHANNELS, 32000, AUDIO_SAMPLERATE);
mResampler48.start(AUDIO_CHANNELS, 48000, AUDIO_SAMPLERATE);
#if defined(DUMP_DECODED) #if defined(DUMP_DECODED)
mDecodedDump = std::make_shared<Audio::WavFileWriter>(); mDecodedDump = std::make_shared<Audio::WavFileWriter>();
mDecodedDump->open("decoded.wav", 8000 /*G711*/, AUDIO_CHANNELS); mDecodedDump->open("decoded.wav", 8000 /*G711*/, AUDIO_CHANNELS);
@@ -906,6 +902,13 @@ void AudioReceiver::ensureDecodeBuffers()
mConvertedFrame.resize(MT_MAX_DECODEBUFFER * 2); mConvertedFrame.resize(MT_MAX_DECODEBUFFER * 2);
mResampledFrame.resize(MT_MAX_DECODEBUFFER); mResampledFrame.resize(MT_MAX_DECODEBUFFER);
} }
if (!mAvailable.capacity())
{
// 10 seconds is the maximum length of decoded audio in single step
// It is important - DTX may produce silence up to few seconds easily
mAvailable.setCapacity(AUDIO_SAMPLERATE * 10 * sizeof(short));
}
} }
void AudioReceiver::makeMonoAndResample(int rate, int channels) void AudioReceiver::makeMonoAndResample(int rate, int channels)
+22 -22
View File
@@ -56,37 +56,37 @@ class RTPMemoryManager;
class JRTPLIB_IMPORTEXPORT RTPIPv4Address : public RTPAddress class JRTPLIB_IMPORTEXPORT RTPIPv4Address : public RTPAddress
{ {
public: public:
/** Creates an instance with IP address \c ip and port number \c port (both are interpreted in host byte order). */ /** Creates an instance with IP address \c ip and port number \c port (both are interpreted in host byte order). */
RTPIPv4Address(uint32_t ip = 0, uint16_t port = 0); RTPIPv4Address(uint32_t ip = 0, uint16_t port = 0);
/** Creates an instance with IP address \c ip and port number \c port (\c port is interpreted in host byte order). */
RTPIPv4Address(const uint8_t ip[4],uint16_t port = 0);
~RTPIPv4Address();
/** Sets the IP address for this instance to \c ip which is assumed to be in host byte order. */ /** Creates an instance with IP address \c ip and port number \c port (\c port is interpreted in host byte order). */
void SetIP(uint32_t ip) { RTPIPv4Address::ip = ip; } RTPIPv4Address(const uint8_t ip[4],uint16_t port = 0);
~RTPIPv4Address();
/** Sets the IP address of this instance to \c ip. */ /** Sets the IP address for this instance to \c ip which is assumed to be in host byte order. */
void SetIP(const uint8_t ip[4]) { RTPIPv4Address::ip = (uint32_t)ip[3]; RTPIPv4Address::ip |= (((uint32_t)ip[2])<<8); RTPIPv4Address::ip |= (((uint32_t)ip[1])<<16); RTPIPv4Address::ip |= (((uint32_t)ip[0])<<24); } void SetIP(uint32_t ip) { RTPIPv4Address::ip = ip; }
/** Sets the port number for this instance to \c port which is interpreted in host byte order. */ /** Sets the IP address of this instance to \c ip. */
void SetPort(uint16_t port) { RTPIPv4Address::port = port; } void SetIP(const uint8_t ip[4]) { RTPIPv4Address::ip = (uint32_t)ip[3]; RTPIPv4Address::ip |= (((uint32_t)ip[2])<<8); RTPIPv4Address::ip |= (((uint32_t)ip[1])<<16); RTPIPv4Address::ip |= (((uint32_t)ip[0])<<24); }
/** Returns the IP address contained in this instance in host byte order. */ /** Sets the port number for this instance to \c port which is interpreted in host byte order. */
uint32_t GetIP() const { return ip; } void SetPort(uint16_t port) { RTPIPv4Address::port = port; }
/** Returns the port number of this instance in host byte order. */ /** Returns the IP address contained in this instance in host byte order. */
uint16_t GetPort() const { return port; } uint32_t GetIP() const { return ip; }
RTPAddress *CreateCopy(RTPMemoryManager *mgr) const; /** Returns the port number of this instance in host byte order. */
bool IsSameAddress(const RTPAddress *addr) const; uint16_t GetPort() const { return port; }
bool IsFromSameHost(const RTPAddress *addr) const;
RTPAddress *CreateCopy(RTPMemoryManager *mgr) const;
bool IsSameAddress(const RTPAddress *addr) const;
bool IsFromSameHost(const RTPAddress *addr) const;
#ifdef RTPDEBUG #ifdef RTPDEBUG
std::string GetAddressString() const; std::string GetAddressString() const;
#endif // RTPDEBUG #endif // RTPDEBUG
private: private:
uint32_t ip; uint32_t ip;
uint16_t port; uint16_t port;
}; };
} // end namespace } // end namespace
+3 -3
View File
@@ -58,7 +58,7 @@ public:
* The flag which indicates whether this data is RTP or RTCP data is set to \c rtp. A memory * 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. * manager can be installed as well.
*/ */
RTPRawPacket(uint8_t *data,size_t datalen,RTPAddress *address,const RTPTime &recvtime,bool rtp,RTPMemoryManager *mgr = 0); RTPRawPacket(uint8_t *data, size_t datalen, RTPAddress *address, const RTPTime &recvtime, bool rtp, RTPMemoryManager *mgr = 0);
~RTPRawPacket(); ~RTPRawPacket();
/** Returns the pointer to the data which is contained in this packet. */ /** Returns the pointer to the data which is contained in this packet. */
@@ -92,7 +92,7 @@ private:
bool isrtp; bool isrtp;
}; };
inline RTPRawPacket::RTPRawPacket(uint8_t *data,size_t datalen,RTPAddress *address, const RTPTime &recvtime,bool rtp,RTPMemoryManager *mgr):RTPMemoryObject(mgr),receivetime(recvtime) inline RTPRawPacket::RTPRawPacket(uint8_t *data, size_t datalen, RTPAddress *address, const RTPTime &recvtime, bool rtp, RTPMemoryManager *mgr):RTPMemoryObject(mgr),receivetime(recvtime)
{ {
packetdata = data; packetdata = data;
packetdatalength = datalen; packetdatalength = datalen;
@@ -103,7 +103,7 @@ inline RTPRawPacket::RTPRawPacket(uint8_t *data,size_t datalen,RTPAddress *addre
inline RTPRawPacket::~RTPRawPacket() inline RTPRawPacket::~RTPRawPacket()
{ {
if (packetdata) if (packetdata)
RTPDeleteByteArray(packetdata,GetMemoryManager()); RTPDeleteByteArray(packetdata,GetMemoryManager());
if (senderaddress) if (senderaddress)
RTPDelete(senderaddress,GetMemoryManager()); RTPDelete(senderaddress,GetMemoryManager());
+6 -2
View File
@@ -9,8 +9,12 @@
using namespace resip; using namespace resip;
Message::Message() : mTu(0) std::atomic<long> Message::sInstanceCount{0};
{}
Message::Message() : mTu(0)
{
++sInstanceCount;
}
Message::Brief Message::Brief
Message::brief() const Message::brief() const
+6 -1
View File
@@ -7,6 +7,7 @@
#include "rutil/Data.hxx" #include "rutil/Data.hxx"
#include <iosfwd> #include <iosfwd>
#include <atomic>
#include "rutil/resipfaststreams.hxx" #include "rutil/resipfaststreams.hxx"
namespace resip namespace resip
@@ -21,7 +22,11 @@ class Message
{ {
public: public:
Message(); Message();
virtual ~Message() {} virtual ~Message() { --sInstanceCount; }
/// Live instance count of all Message-derived objects (leak indicator).
static std::atomic<long> sInstanceCount;
static long getInstanceCount() { return sInstanceCount.load(std::memory_order_relaxed); }
/// facet for brief output to streams /// facet for brief output to streams
class Brief class Brief
@@ -28,6 +28,8 @@ using namespace std;
bool SipMessage::checkContentLength=true; bool SipMessage::checkContentLength=true;
std::atomic<long> SipMessage::sInstanceCount{0};
SipMessage::SipMessage(const Tuple *receivedTransportTuple) SipMessage::SipMessage(const Tuple *receivedTransportTuple)
: mIsDecorated(false), : mIsDecorated(false),
mIsBadAck200(false), mIsBadAck200(false),
@@ -51,6 +53,7 @@ SipMessage::SipMessage(const Tuple *receivedTransportTuple)
// !bwc! TODO make this tunable // !bwc! TODO make this tunable
mHeaders.reserve(16); mHeaders.reserve(16);
clear(); clear();
++sInstanceCount;
} }
SipMessage::SipMessage(const SipMessage& from) SipMessage::SipMessage(const SipMessage& from)
@@ -63,6 +66,7 @@ SipMessage::SipMessage(const SipMessage& from)
mCreatedTime(Timer::getTimeMicroSec()) mCreatedTime(Timer::getTimeMicroSec())
{ {
init(from); init(from);
++sInstanceCount;
} }
Message* Message*
@@ -98,6 +102,7 @@ SipMessage::~SipMessage()
} }
#endif #endif
freeMem(); freeMem();
--sInstanceCount;
} }
void void
@@ -6,7 +6,8 @@
#include <list> #include <list>
#include <vector> #include <vector>
#include <utility> #include <utility>
#include <memory> #include <memory>
#include <atomic>
#include "resip/stack/Contents.hxx" #include "resip/stack/Contents.hxx"
#include "resip/stack/Headers.hxx" #include "resip/stack/Headers.hxx"
@@ -154,6 +155,10 @@ class SipMessage : public TransactionMessage
{ {
public: public:
RESIP_HeapCount(SipMessage); RESIP_HeapCount(SipMessage);
/// Live instance count of SipMessage objects (leak indicator).
static std::atomic<long> sInstanceCount;
static long getInstanceCount() { return sInstanceCount.load(std::memory_order_relaxed); }
#ifndef __SUNPRO_CC #ifndef __SUNPRO_CC
typedef std::list< std::pair<Data, HeaderFieldValueList*>, StlPoolAllocator<std::pair<Data, HeaderFieldValueList*>, PoolBase > > UnknownHeaders; typedef std::list< std::pair<Data, HeaderFieldValueList*>, StlPoolAllocator<std::pair<Data, HeaderFieldValueList*>, PoolBase > > UnknownHeaders;
#else #else