This commit is contained in:
2026-01-30 08:25:17 +03:00
parent 155c6fd691
commit 260413fad1
10 changed files with 130 additions and 116 deletions

View File

@@ -5,6 +5,7 @@
#include "helper/HL_VariantMap.h"
#include "helper/HL_CsvReader.h"
#include "helper/HL_Base64.h"
#include "media/MT_CodecList.h"
#include <fstream>
@@ -210,7 +211,8 @@ void AgentImpl::processStart(JsonCpp::Value& request, JsonCpp::Value &answer)
SocketHeap::instance().start();
// Initialize terminal
MT::CodecList::Settings settings;
auto settings = MT::CodecList::Settings::getClientSettings();
mTerminal = std::make_shared<MT::Terminal>(settings);
// Enable/disable codecs
@@ -220,10 +222,10 @@ void AgentImpl::processStart(JsonCpp::Value& request, JsonCpp::Value &answer)
priorityConfig->at(i) = i;
// Disable dynamic payload codec types - commented for now
/*if (cl.codecAt(i).payloadType() < 96)
priorityConfig->at(i) = i;
else
priorityConfig->at(i) = -1;*/
// if (cl.codecAt(i).payloadType() < 96)
// priorityConfig->at(i) = i;
// else
// priorityConfig->at(i) = -1;
config()[CONFIG_CODEC_PRIORITY] = priorityConfig;

View File

@@ -423,13 +423,13 @@ bool AudioReceiver::add(const std::shared_ptr<jrtplib::RTPPacket>& p, Codec** de
payloadLength = p->GetPayloadLength(),
ptype = p->GetPayloadType();
// ICELogInfo(<< "Adding packet No " << p->GetSequenceNumber());
ICELogInfo(<< "Adding packet No " << p->GetSequenceNumber());
// Increase codec counter
mStat.mCodecCount[ptype]++;
// Check if codec can be handled
Codec* codec = nullptr;
CodecMap::iterator codecIter = mCodecMap.find(ptype);
auto codecIter = mCodecMap.find(ptype);
if (codecIter == mCodecMap.end())
{
time_length = 10;
@@ -618,7 +618,17 @@ AudioReceiver::DecodeResult AudioReceiver::decodePacket(const RtpBuffer::ResultL
// Find codec by payload type
int ptype = p->rtp()->GetPayloadType();
mCodec = mCodecMap[ptype];
// Look into mCodecMap if exists
auto codecIter = mCodecMap.find(ptype);
if (codecIter == mCodecMap.end())
return {};
if (!codecIter->second)
codecIter->second = mCodecList.createCodecByPayloadType(ptype);
mCodec = codecIter->second;
if (mCodec)
{
if (rate)
@@ -695,7 +705,7 @@ AudioReceiver::DecodeResult AudioReceiver::decodePacket(const RtpBuffer::ResultL
AudioReceiver::DecodeResult AudioReceiver::decodeNone(Audio::DataWindow& output, DecodeOptions options)
{
ICELogDebug(<< "No packet available in jitter buffer");
// ICELogDebug(<< "No packet available in jitter buffer");
mFailedCount++;
return DecodeResult_Skip;
}

View File

@@ -225,9 +225,9 @@ void AudioStream::addData(const void* buffer, int bytes)
if (packetTime <= encodedTime)
{
// Time to send packet
ICELogMedia(<< "Sending RTP packet pt = " << mTransmittingPayloadType << ", plength = " << (int)mEncodedAudio.size());
ICELogMedia(<< "Sending RTP packet pt = " << mTransmittingPayloadType << ", plength = " << (int)mEncodedAudio.size() << " to ");
mRtpSession.SendPacketEx(mEncodedAudio.data(), mEncodedAudio.size(), mTransmittingPayloadType, false,
packetTime * codec->samplerate()/1000, 0, NULL, 0);
packetTime * codec->samplerate()/1000, 0, nullptr, 0);
mEncodedAudio.clear();
encodedTime = 0;
}
@@ -365,9 +365,11 @@ void AudioStream::dataArrived(PDatagramSocket s, const void* buffer, int length,
// Find right handler for rtp stream
SingleAudioStream* rtpStream = nullptr;
AudioStreamMap::iterator streamIter = mStreamMap.find(packet->GetSSRC());
if (streamIter == mStreamMap.end())
mStreamMap[packet->GetSSRC()] = rtpStream = new SingleAudioStream(mCodecSettings, mStat);
auto streamIter = mStreamMap.find(packet->GetSSRC());
if (streamIter == mStreamMap.end()) {
rtpStream = new SingleAudioStream(mCodecSettings, mStat);
mStreamMap.insert({packet->GetSSRC(), rtpStream});
}
else
rtpStream = streamIter->second;

View File

@@ -62,16 +62,16 @@ public:
protected:
Audio::DataWindow mCapturedAudio; // Data from microphone
Audio::DataWindow mStereoCapturedAudio;
char mIncomingPcmBuffer[AUDIO_MIC_BUFFER_SIZE]; // Temporary buffer to allow reading from file
char mResampleBuffer[AUDIO_MIC_BUFFER_SIZE*8]; // Temporary buffer to hold data
char mStereoBuffer[AUDIO_MIC_BUFFER_SIZE*16]; // Temporary buffer to hold data converted to stereo
char mIncomingPcmBuffer[AUDIO_MIC_BUFFER_SIZE] = {0}; // Temporary buffer to allow reading from file
char mResampleBuffer[AUDIO_MIC_BUFFER_SIZE*8] = {0}; // Temporary buffer to hold data
char mStereoBuffer[AUDIO_MIC_BUFFER_SIZE*16] = {0}; // Temporary buffer to hold data converted to stereo
PCodec mTransmittingCodec; // Current encoding codec
int mTransmittingPayloadType; // Payload type to mark outgoing packets
int mPacketTime; // Required packet time
int mTransmittingPayloadType = -1; // Payload type to mark outgoing packets
int mPacketTime = 0; // Required packet time
char mFrameBuffer[MT_MAXAUDIOFRAME]; // Temporary buffer to hold results of encoder
ByteBuffer mEncodedAudio; // Encoded frame(s)
int mEncodedTime; // Time length of encoded audio
const CodecList::Settings& mCodecSettings; // Configuration for stream
int mEncodedTime = 0; // Time length of encoded audio
CodecList::Settings mCodecSettings; // Configuration for stream
Mutex mMutex; // Mutex
int mRemoteTelephoneCodec; // Payload for remote telephone codec
jrtplib::RTPSession mRtpSession; // Rtp session
@@ -83,12 +83,12 @@ protected:
RtpDump* mRtpDump = nullptr;
#endif
Audio::Resampler mCaptureResampler8,
mCaptureResampler16,
mCaptureResampler32,
mCaptureResampler48;
mCaptureResampler16,
mCaptureResampler32,
mCaptureResampler48;
DtmfContext mDtmfContext;
char mReceiveBuffer[MAX_VALID_UDPPACKET_SIZE],
mSrtpDecodeBuffer[MAX_VALID_UDPPACKET_SIZE];
char mReceiveBuffer[MAX_VALID_UDPPACKET_SIZE] = {0},
mSrtpDecodeBuffer[MAX_VALID_UDPPACKET_SIZE] = {0};
struct
{
@@ -106,7 +106,7 @@ protected:
Statistics* mFinalStatistics = nullptr;
bool decryptSrtp(void* data, int* len);
// bool decryptSrtp(void* data, int* len);
};
};

View File

@@ -40,7 +40,7 @@ PStream Terminal::createStream(int type, VariantMap& /*config*/)
switch (type)
{
case Stream::Audio:
result = std::make_shared<AudioStream>(MT::CodecList::Settings::DefaultSettings);
result = std::make_shared<AudioStream>(MT::CodecList::Settings::getClientSettings());
mAudioList.add(result);
break;

View File

@@ -25,6 +25,17 @@ using namespace MT;
using strx = strx;
CodecList::Settings CodecList::Settings::getAnalyzerSettings()
{
return {};
}
CodecList::Settings CodecList::Settings::getClientSettings()
{
Settings r;
r.mOpusSpec.push_back(Settings::OpusSpec(MT_OPUS_CODEC_PT, 48000, 2));
return r;
}
bool CodecList::Settings::contains(int ptype) const
{
@@ -223,7 +234,7 @@ static int findOctetMode(const char* line)
CodecList::Settings CodecList::Settings::parseSdp(const std::list<resip::Codec>& codeclist)
{
CodecList::Settings r{DefaultSettings};
CodecList::Settings r;
for (auto& c: codeclist)
{
@@ -235,41 +246,27 @@ CodecList::Settings CodecList::Settings::parseSdp(const std::list<resip::Codec>&
auto params = c.parameters();
// Dynamic payload type codecs only - ISAC / iLBC / Speex / etc.
if (codec_name == "OPUS")
{
if (codec_name == "OPUS") {
// Check the parameters
int channels = strx::toInt(enc_params.c_str(), 1);
r.mOpusSpec.push_back({ptype, samplerate, channels});
}
else
if (codec_name == "AMR-WB")
{
} else if (codec_name == "AMR-WB") {
int octet_mode = findOctetMode(params.c_str());
if (octet_mode != -1)
{
if (octet_mode != -1) {
if (octet_mode == 0)
r.mAmrWbPayloadType.insert(ptype);
else
if (octet_mode == 1)
else if (octet_mode == 1)
r.mAmrWbOctetPayloadType.insert(ptype);
}
}
else
if (codec_name == "AMR" || codec_name == "AMR-NB")
{
} else if (codec_name == "AMR" || codec_name == "AMR-NB") {
int octet_mode = findOctetMode(params.c_str());
if (octet_mode != -1)
{
if (octet_mode != -1) {
if (octet_mode == 0)
r.mAmrNbPayloadType.insert(ptype);
else
if (octet_mode == 1)
else if (octet_mode == 1)
r.mAmrNbOctetPayloadType.insert(ptype);
}
}
else
if (codec_name == "EVS")
{
} else if (codec_name == "EVS") {
r.mEvsSpec.push_back({ptype});
}
}
@@ -314,7 +311,6 @@ bool CodecList::Settings::operator == (const Settings& rhs) const
// ----------------------------------------
CodecList::Settings CodecList::Settings::DefaultSettings;
CodecList::CodecList(const Settings& settings)
:mSettings(settings)
@@ -405,8 +401,8 @@ void CodecList::fillCodecMap(CodecMap& cm)
for (auto& factory: mFactoryList)
{
// Create codec here. Although they are not needed right now - they can be needed to find codec's info.
// PCodec c = factory->create();
cm.insert({factory->payloadType(), PCodec()});
PCodec c = factory->create();
cm.insert({factory->payloadType(), c});
}
}
@@ -438,7 +434,7 @@ bool CodecListPriority::compare(const Item& item1, const Item& item2)
void CodecListPriority::setupFrom(PVariantMap vmap)
{
CodecList::Settings settings;
auto settings = CodecList::Settings::getClientSettings();
CodecList cl(settings);
//mPriorityList.resize(cl.count());
bool emptyVmap = vmap ? vmap->empty() : true;

View File

@@ -101,11 +101,12 @@ public:
std::string toString() const;
void clear();
static Settings DefaultSettings;
static Settings parseSdp(const std::list<resip::Codec>& codeclist);
bool operator == (const Settings& rhs) const;
static Settings getClientSettings();
static Settings getAnalyzerSettings();
};
CodecList(const Settings& settings);

View File

@@ -1,15 +1,17 @@
/* Copyright(C) 2007-2019 VoIP objects (voipobjects.com)
/* Copyright(C) 2007-2026 VoIP objects (voipobjects.com)
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "MT_NativeRtpSender.h"
#include "ICELog.h"
#include <assert.h>
#define LOG_SUBSYSTEM "MT"
using namespace MT;
NativeRtpSender::NativeRtpSender(Statistics& stat)
:mStat(stat), mSrtpSession(nullptr)
:mStat(stat), mSrtpSession(nullptr)
{
}
@@ -19,107 +21,108 @@ NativeRtpSender::~NativeRtpSender()
bool NativeRtpSender::SendRTP(const void *data, size_t len)
{
if (mTarget.mRtp.isEmpty() || !mSocket.mRtp)
return false;
if (mTarget.mRtp.isEmpty() || !mSocket.mRtp)
return false;
#if defined(USE_RTPDUMP)
if (mDumpWriter)
mDumpWriter->add(data, len);
if (mDumpWriter)
mDumpWriter->add(data, len);
#endif
// Copy data to intermediary buffer bigger that original
int sendLength = len;
memcpy(mSendBuffer, data, len);
// Copy data to intermediary buffer bigger that original
int sendLength = len;
memcpy(mSendBuffer, data, len);
// Encrypt SRTP if needed
if (mSrtpSession)
{
if (mSrtpSession->active())
// Encrypt SRTP if needed
if (mSrtpSession)
{
if (!mSrtpSession->protectRtp(mSendBuffer, &sendLength))
return false;
if (mSrtpSession->active())
{
if (!mSrtpSession->protectRtp(mSendBuffer, &sendLength))
return false;
}
}
}
mSocket.mRtp->sendDatagram(mTarget.mRtp, mSendBuffer, sendLength);
mStat.mSentRtp++;
mStat.mSent += len;
ICELogInfo(<< "Sending " << sendLength <<" bytes to " << mTarget.mRtp.toBriefStdString());
mSocket.mRtp->sendDatagram(mTarget.mRtp, mSendBuffer, sendLength);
mStat.mSentRtp++;
mStat.mSent += len;
return true;
return true;
}
/** This member function will be called when an RTCP packet needs to be transmitted. */
bool NativeRtpSender::SendRTCP(const void *data, size_t len)
{
if (mTarget.mRtp.isEmpty() || !mSocket.mRtcp)
return false;
// Copy data to intermediary buffer bigger that original
int sendLength = len;
memcpy(mSendBuffer, data, len);
// Encrypt SRTP if needed
if (mSrtpSession)
{
if (mSrtpSession->active())
{
if (!mSrtpSession->protectRtcp(mSendBuffer, &sendLength))
if (mTarget.mRtp.isEmpty() || !mSocket.mRtcp)
return false;
// Copy data to intermediary buffer bigger that original
int sendLength = len;
memcpy(mSendBuffer, data, len);
// Encrypt SRTP if needed
if (mSrtpSession)
{
if (mSrtpSession->active())
{
if (!mSrtpSession->protectRtcp(mSendBuffer, &sendLength))
return false;
}
}
}
mSocket.mRtcp->sendDatagram(mTarget.mRtcp, mSendBuffer, sendLength);
mStat.mSentRtcp++;
mStat.mSent += len;
mSocket.mRtcp->sendDatagram(mTarget.mRtcp, mSendBuffer, sendLength);
mStat.mSentRtcp++;
mStat.mSent += len;
return true;
return true;
}
/** Used to identify if an RTPAddress instance originated from this sender (to be able to detect own packets). */
bool NativeRtpSender::ComesFromThisSender(const jrtplib::RTPAddress *a)
{
return false;
return false;
}
void NativeRtpSender::setDestination(RtpPair<InternetAddress> target)
{
mTarget = target;
mTarget = target;
}
RtpPair<InternetAddress> NativeRtpSender::destination()
{
return mTarget;
return mTarget;
}
void NativeRtpSender::setSocket(const RtpPair<PDatagramSocket>& socket)
{
mSocket = socket;
mSocket = socket;
}
RtpPair<PDatagramSocket>& NativeRtpSender::socket()
{
return mSocket;
return mSocket;
}
#if defined(USE_RTPDUMP)
void NativeRtpSender::setDumpWriter(RtpDump *dump)
{
mDumpWriter = dump;
mDumpWriter = dump;
}
RtpDump* NativeRtpSender::dumpWriter()
{
return mDumpWriter;
return mDumpWriter;
}
#endif
void NativeRtpSender::setSrtpSession(SrtpSession* srtp)
{
mSrtpSession = srtp;
mSrtpSession = srtp;
}
SrtpSession* NativeRtpSender::srtpSession()
{
return mSrtpSession;
return mSrtpSession;
}

View File

@@ -18,19 +18,19 @@
namespace MT
{
class NativeRtpSender: public jrtplib::RTPExternalSender
{
public:
class NativeRtpSender: public jrtplib::RTPExternalSender
{
public:
NativeRtpSender(Statistics& stat);
~NativeRtpSender();
/** This member function will be called when RTP data needs to be transmitted. */
bool SendRTP(const void *data, size_t len);
/** This member function will be called when RTP data needs to be transmitted. */
bool SendRTP(const void *data, size_t len);
/** This member function will be called when an RTCP packet needs to be transmitted. */
bool SendRTCP(const void *data, size_t len);
/** This member function will be called when an RTCP packet needs to be transmitted. */
bool SendRTCP(const void *data, size_t len);
/** Used to identify if an RTPAddress instance originated from this sender (to be able to detect own packets). */
/** Used to identify if an RTPAddress instance originated from this sender (to be able to detect own packets). */
bool ComesFromThisSender(const jrtplib::RTPAddress *a);
void setDestination(RtpPair<InternetAddress> destination);
@@ -46,7 +46,7 @@ namespace MT
void setSrtpSession(SrtpSession* srtp);
SrtpSession* srtpSession();
protected:
protected:
RtpPair<PDatagramSocket> mSocket;
RtpPair<InternetAddress> mTarget;
Statistics& mStat;
@@ -55,7 +55,7 @@ namespace MT
#endif
SrtpSession* mSrtpSession;
char mSendBuffer[MAX_VALID_UDPPACKET_SIZE];
};
};
}
#endif

View File

@@ -39,7 +39,7 @@ void SingleAudioStream::copyPcmTo(Audio::DataWindow& output, int needed)
break;
}
if (output.filled() < needed)
ICELogError(<< "Not enough data for speaker's mixer");
// if (output.filled() < needed)
// ICELogError(<< "Not enough data for speaker's mixer");
}