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_VariantMap.h"
#include "helper/HL_CsvReader.h" #include "helper/HL_CsvReader.h"
#include "helper/HL_Base64.h" #include "helper/HL_Base64.h"
#include "media/MT_CodecList.h"
#include <fstream> #include <fstream>
@@ -210,7 +211,8 @@ void AgentImpl::processStart(JsonCpp::Value& request, JsonCpp::Value &answer)
SocketHeap::instance().start(); SocketHeap::instance().start();
// Initialize terminal // Initialize terminal
MT::CodecList::Settings settings; auto settings = MT::CodecList::Settings::getClientSettings();
mTerminal = std::make_shared<MT::Terminal>(settings); mTerminal = std::make_shared<MT::Terminal>(settings);
// Enable/disable codecs // Enable/disable codecs
@@ -220,10 +222,10 @@ void AgentImpl::processStart(JsonCpp::Value& request, JsonCpp::Value &answer)
priorityConfig->at(i) = i; priorityConfig->at(i) = i;
// Disable dynamic payload codec types - commented for now // Disable dynamic payload codec types - commented for now
/*if (cl.codecAt(i).payloadType() < 96) // if (cl.codecAt(i).payloadType() < 96)
priorityConfig->at(i) = i; // priorityConfig->at(i) = i;
else // else
priorityConfig->at(i) = -1;*/ // priorityConfig->at(i) = -1;
config()[CONFIG_CODEC_PRIORITY] = priorityConfig; 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(), payloadLength = p->GetPayloadLength(),
ptype = p->GetPayloadType(); ptype = p->GetPayloadType();
// ICELogInfo(<< "Adding packet No " << p->GetSequenceNumber()); ICELogInfo(<< "Adding packet No " << p->GetSequenceNumber());
// Increase codec counter // Increase codec counter
mStat.mCodecCount[ptype]++; mStat.mCodecCount[ptype]++;
// Check if codec can be handled // Check if codec can be handled
Codec* codec = nullptr; Codec* codec = nullptr;
CodecMap::iterator codecIter = mCodecMap.find(ptype); auto codecIter = mCodecMap.find(ptype);
if (codecIter == mCodecMap.end()) if (codecIter == mCodecMap.end())
{ {
time_length = 10; time_length = 10;
@@ -618,7 +618,17 @@ AudioReceiver::DecodeResult AudioReceiver::decodePacket(const RtpBuffer::ResultL
// Find codec by payload type // Find codec by payload type
int ptype = p->rtp()->GetPayloadType(); 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 (mCodec)
{ {
if (rate) if (rate)
@@ -695,7 +705,7 @@ AudioReceiver::DecodeResult AudioReceiver::decodePacket(const RtpBuffer::ResultL
AudioReceiver::DecodeResult AudioReceiver::decodeNone(Audio::DataWindow& output, DecodeOptions options) AudioReceiver::DecodeResult AudioReceiver::decodeNone(Audio::DataWindow& output, DecodeOptions options)
{ {
ICELogDebug(<< "No packet available in jitter buffer"); // ICELogDebug(<< "No packet available in jitter buffer");
mFailedCount++; mFailedCount++;
return DecodeResult_Skip; return DecodeResult_Skip;
} }

View File

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

View File

@@ -62,16 +62,16 @@ public:
protected: protected:
Audio::DataWindow mCapturedAudio; // Data from microphone Audio::DataWindow mCapturedAudio; // Data from microphone
Audio::DataWindow mStereoCapturedAudio; Audio::DataWindow mStereoCapturedAudio;
char mIncomingPcmBuffer[AUDIO_MIC_BUFFER_SIZE]; // Temporary buffer to allow reading from file char mIncomingPcmBuffer[AUDIO_MIC_BUFFER_SIZE] = {0}; // Temporary buffer to allow reading from file
char mResampleBuffer[AUDIO_MIC_BUFFER_SIZE*8]; // Temporary buffer to hold data char mResampleBuffer[AUDIO_MIC_BUFFER_SIZE*8] = {0}; // Temporary buffer to hold data
char mStereoBuffer[AUDIO_MIC_BUFFER_SIZE*16]; // Temporary buffer to hold data converted to stereo char mStereoBuffer[AUDIO_MIC_BUFFER_SIZE*16] = {0}; // Temporary buffer to hold data converted to stereo
PCodec mTransmittingCodec; // Current encoding codec PCodec mTransmittingCodec; // Current encoding codec
int mTransmittingPayloadType; // Payload type to mark outgoing packets int mTransmittingPayloadType = -1; // Payload type to mark outgoing packets
int mPacketTime; // Required packet time int mPacketTime = 0; // Required packet time
char mFrameBuffer[MT_MAXAUDIOFRAME]; // Temporary buffer to hold results of encoder char mFrameBuffer[MT_MAXAUDIOFRAME]; // Temporary buffer to hold results of encoder
ByteBuffer mEncodedAudio; // Encoded frame(s) ByteBuffer mEncodedAudio; // Encoded frame(s)
int mEncodedTime; // Time length of encoded audio int mEncodedTime = 0; // Time length of encoded audio
const CodecList::Settings& mCodecSettings; // Configuration for stream CodecList::Settings mCodecSettings; // Configuration for stream
Mutex mMutex; // Mutex Mutex mMutex; // Mutex
int mRemoteTelephoneCodec; // Payload for remote telephone codec int mRemoteTelephoneCodec; // Payload for remote telephone codec
jrtplib::RTPSession mRtpSession; // Rtp session jrtplib::RTPSession mRtpSession; // Rtp session
@@ -87,8 +87,8 @@ protected:
mCaptureResampler32, mCaptureResampler32,
mCaptureResampler48; mCaptureResampler48;
DtmfContext mDtmfContext; DtmfContext mDtmfContext;
char mReceiveBuffer[MAX_VALID_UDPPACKET_SIZE], char mReceiveBuffer[MAX_VALID_UDPPACKET_SIZE] = {0},
mSrtpDecodeBuffer[MAX_VALID_UDPPACKET_SIZE]; mSrtpDecodeBuffer[MAX_VALID_UDPPACKET_SIZE] = {0};
struct struct
{ {
@@ -106,7 +106,7 @@ protected:
Statistics* mFinalStatistics = nullptr; 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) switch (type)
{ {
case Stream::Audio: case Stream::Audio:
result = std::make_shared<AudioStream>(MT::CodecList::Settings::DefaultSettings); result = std::make_shared<AudioStream>(MT::CodecList::Settings::getClientSettings());
mAudioList.add(result); mAudioList.add(result);
break; break;

View File

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

View File

@@ -101,11 +101,12 @@ public:
std::string toString() const; std::string toString() const;
void clear(); void clear();
static Settings DefaultSettings;
static Settings parseSdp(const std::list<resip::Codec>& codeclist); static Settings parseSdp(const std::list<resip::Codec>& codeclist);
bool operator == (const Settings& rhs) const; bool operator == (const Settings& rhs) const;
static Settings getClientSettings();
static Settings getAnalyzerSettings();
}; };
CodecList(const Settings& settings); 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 * 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 * 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/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "MT_NativeRtpSender.h" #include "MT_NativeRtpSender.h"
#include "ICELog.h"
#include <assert.h> #include <assert.h>
#define LOG_SUBSYSTEM "MT"
using namespace MT; using namespace MT;
NativeRtpSender::NativeRtpSender(Statistics& stat) NativeRtpSender::NativeRtpSender(Statistics& stat)
:mStat(stat), mSrtpSession(nullptr) :mStat(stat), mSrtpSession(nullptr)
{ {
} }
@@ -41,6 +43,7 @@ bool NativeRtpSender::SendRTP(const void *data, size_t len)
} }
} }
ICELogInfo(<< "Sending " << sendLength <<" bytes to " << mTarget.mRtp.toBriefStdString());
mSocket.mRtp->sendDatagram(mTarget.mRtp, mSendBuffer, sendLength); mSocket.mRtp->sendDatagram(mTarget.mRtp, mSendBuffer, sendLength);
mStat.mSentRtp++; mStat.mSentRtp++;
mStat.mSent += len; mStat.mSent += len;

View File

@@ -18,9 +18,9 @@
namespace MT namespace MT
{ {
class NativeRtpSender: public jrtplib::RTPExternalSender class NativeRtpSender: public jrtplib::RTPExternalSender
{ {
public: public:
NativeRtpSender(Statistics& stat); NativeRtpSender(Statistics& stat);
~NativeRtpSender(); ~NativeRtpSender();
@@ -46,7 +46,7 @@ namespace MT
void setSrtpSession(SrtpSession* srtp); void setSrtpSession(SrtpSession* srtp);
SrtpSession* srtpSession(); SrtpSession* srtpSession();
protected: protected:
RtpPair<PDatagramSocket> mSocket; RtpPair<PDatagramSocket> mSocket;
RtpPair<InternetAddress> mTarget; RtpPair<InternetAddress> mTarget;
Statistics& mStat; Statistics& mStat;
@@ -55,7 +55,7 @@ namespace MT
#endif #endif
SrtpSession* mSrtpSession; SrtpSession* mSrtpSession;
char mSendBuffer[MAX_VALID_UDPPACKET_SIZE]; char mSendBuffer[MAX_VALID_UDPPACKET_SIZE];
}; };
} }
#endif #endif

View File

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