diff --git a/src/engine/engine_config.h b/src/engine/engine_config.h index e0d14490..a0ba0390 100644 --- a/src/engine/engine_config.h +++ b/src/engine/engine_config.h @@ -46,13 +46,17 @@ #define MT_SAMPLERATE AUDIO_SAMPLERATE -#define MT_MAXAUDIOFRAME 1440 -#define MT_MAXRTPPACKET 1500 -#define MT_DTMF_END_PACKETS 3 +#define MT_MAXAUDIOFRAME 1440 +#define MT_MAXRTPPACKET 1500 +#define MT_DTMF_END_PACKETS 3 -#define RTP_BUFFER_HIGH 480 -#define RTP_BUFFER_LOW 10 -#define RTP_BUFFER_PREBUFFER 320 +#define RTP_BUFFER_HIGH 0 +#define RTP_BUFFER_LOW 0 +#define RTP_BUFFER_PREBUFFER 0 + +// #define RTP_BUFFER_HIGH 160 +// #define RTP_BUFFER_LOW 10 +// #define RTP_BUFFER_PREBUFFER 160 #define RTP_DECODED_CAPACITY 2048 #define DEFAULT_SUBSCRIPTION_TIME 1200 diff --git a/src/engine/media/MT_AmrCodec.cpp b/src/engine/media/MT_AmrCodec.cpp index 2ae9a361..d0be326e 100644 --- a/src/engine/media/MT_AmrCodec.cpp +++ b/src/engine/media/MT_AmrCodec.cpp @@ -543,6 +543,7 @@ PCodec AmrWbCodec::CodecFactory::create() return PCodec(new AmrWbCodec(mConfig)); } +AmrWbStatistics MT::GAmrWbStatistics; AmrWbCodec::AmrWbCodec(const AmrCodecConfig& config) :mEncoderCtx(nullptr), mDecoderCtx(nullptr), mConfig(config), @@ -672,6 +673,7 @@ int AmrWbCodec::decode(const void* input, int inputBytes, void* output, int outp } catch(...) { + GAmrWbStatistics.mNonParsed++; ICELogDebug(<< "Failed to decode AMR payload"); return 0; } @@ -680,8 +682,10 @@ int AmrWbCodec::decode(const void* input, int inputBytes, void* output, int outp // Check if packet is corrupted if (ap.mDiscardPacket) + { + GAmrWbStatistics.mDiscarded++; return 0; - + } // Check for output buffer capacity if (outputCapacity < (int)ap.mFrames.size() * pcmLength()) return 0; diff --git a/src/engine/media/MT_AmrCodec.h b/src/engine/media/MT_AmrCodec.h index dddc02a3..667b8d33 100644 --- a/src/engine/media/MT_AmrCodec.h +++ b/src/engine/media/MT_AmrCodec.h @@ -14,16 +14,16 @@ namespace MT { - struct AmrCodecConfig - { +struct AmrCodecConfig +{ bool mIuUP; bool mOctetAligned; int mPayloadType; - }; +}; - class AmrNbCodec : public Codec - { - protected: +class AmrNbCodec : public Codec +{ +protected: void* mEncoderCtx; void* mDecoderCtx; AmrCodecConfig mConfig; @@ -31,25 +31,25 @@ namespace MT int mSwitchCounter; int mPreviousPacketLength; - public: +public: class CodecFactory: public Factory { public: - CodecFactory(const AmrCodecConfig& config); + CodecFactory(const AmrCodecConfig& config); - const char* name() override; - int samplerate() override; - int payloadType() override; + const char* name() override; + int samplerate() override; + int payloadType() override; #ifdef USE_RESIP_INTEGRATION - void updateSdp(resip::SdpContents::Session::Medium::CodecContainer& codecs, SdpDirection direction) override; - int processSdp(const resip::SdpContents::Session::Medium::CodecContainer& codecs, SdpDirection direction) override; - void create(CodecMap& codecs) override; + void updateSdp(resip::SdpContents::Session::Medium::CodecContainer& codecs, SdpDirection direction) override; + int processSdp(const resip::SdpContents::Session::Medium::CodecContainer& codecs, SdpDirection direction) override; + void create(CodecMap& codecs) override; #endif - PCodec create() override; + PCodec create() override; protected: - AmrCodecConfig mConfig; + AmrCodecConfig mConfig; }; AmrNbCodec(const AmrCodecConfig& config); @@ -64,11 +64,18 @@ namespace MT int decode(const void* input, int inputBytes, void* output, int outputCapacity) override; int plc(int lostFrames, void* output, int outputCapacity) override; int getSwitchCounter() const; - }; +}; - class AmrWbCodec : public Codec - { - protected: +struct AmrWbStatistics +{ + int mDiscarded = 0; + int mNonParsed = 0; +}; +extern AmrWbStatistics GAmrWbStatistics; + +class AmrWbCodec : public Codec +{ +protected: void* mEncoderCtx; void* mDecoderCtx; AmrCodecConfig mConfig; @@ -76,25 +83,25 @@ namespace MT int mSwitchCounter; int mPreviousPacketLength; - public: +public: class CodecFactory: public Factory { public: - CodecFactory(const AmrCodecConfig& config); + CodecFactory(const AmrCodecConfig& config); - const char* name() override; - int samplerate() override; - int payloadType() override; + const char* name() override; + int samplerate() override; + int payloadType() override; #ifdef USE_RESIP_INTEGRATION - void updateSdp(resip::SdpContents::Session::Medium::CodecContainer& codecs, SdpDirection direction) override; - int processSdp(const resip::SdpContents::Session::Medium::CodecContainer& codecs, SdpDirection direction) override; - void create(CodecMap& codecs) override; + void updateSdp(resip::SdpContents::Session::Medium::CodecContainer& codecs, SdpDirection direction) override; + int processSdp(const resip::SdpContents::Session::Medium::CodecContainer& codecs, SdpDirection direction) override; + void create(CodecMap& codecs) override; #endif - PCodec create() override; + PCodec create() override; protected: - AmrCodecConfig mConfig; + AmrCodecConfig mConfig; }; AmrWbCodec(const AmrCodecConfig& config); @@ -109,35 +116,35 @@ namespace MT int decode(const void* input, int inputBytes, void* output, int outputCapacity) override; int plc(int lostFrames, void* output, int outputCapacity) override; int getSwitchCounter() const; - }; +}; - class GsmEfrCodec : public Codec - { - protected: +class GsmEfrCodec : public Codec +{ +protected: void* mEncoderCtx; void* mDecoderCtx; bool mIuUP; - public: +public: class GsmEfrFactory: public Factory { public: - GsmEfrFactory(bool iuup, int ptype); + GsmEfrFactory(bool iuup, int ptype); - const char* name() override; - int samplerate() override; - int payloadType() override; + const char* name() override; + int samplerate() override; + int payloadType() override; #ifdef USE_RESIP_INTEGRATION - void updateSdp(resip::SdpContents::Session::Medium::CodecContainer& codecs, SdpDirection direction) override; - int processSdp(const resip::SdpContents::Session::Medium::CodecContainer& codecs, SdpDirection direction) override; - void create(CodecMap& codecs) override; + void updateSdp(resip::SdpContents::Session::Medium::CodecContainer& codecs, SdpDirection direction) override; + int processSdp(const resip::SdpContents::Session::Medium::CodecContainer& codecs, SdpDirection direction) override; + void create(CodecMap& codecs) override; #endif - PCodec create() override; + PCodec create() override; protected: - bool mIuUP; - int mPayloadType; + bool mIuUP; + int mPayloadType; }; GsmEfrCodec(bool iuup = false); @@ -151,7 +158,7 @@ namespace MT int encode(const void* input, int inputBytes, void* output, int outputCapacity) override; int decode(const void* input, int inputBytes, void* output, int outputCapacity) override; int plc(int lostFrames, void* output, int outputCapacity) override; - }; +}; } // End of MT namespace diff --git a/src/engine/media/MT_AudioReceiver.cpp b/src/engine/media/MT_AudioReceiver.cpp index b6bf4609..5b735b88 100644 --- a/src/engine/media/MT_AudioReceiver.cpp +++ b/src/engine/media/MT_AudioReceiver.cpp @@ -197,7 +197,7 @@ RtpBuffer::FetchResult RtpBuffer::fetch(ResultList& rl) // See if there is enough information in buffer int total = findTimelength(); - while (total > mHigh && mPacketList.size()) + while (total > mHigh && mPacketList.size() && 0 != mHigh) { ICELogMedia( << "Dropping RTP packets from jitter buffer"); total -= mPacketList.front()->timelength(); @@ -356,11 +356,17 @@ void AudioReceiver::setCodecSettings(const CodecList::Settings& codecSettings) return; mCodecSettings = codecSettings; - mCodecMap.clear(); - mCodecList.setSettings(mCodecSettings); + mCodecList.setSettings(mCodecSettings); // This builds factory list with proper payload types according to payload types in settings + + // Rebuild codec map from factory list mCodecList.fillCodecMap(mCodecMap); } +CodecList::Settings& AudioReceiver::getCodecSettings() +{ + return mCodecSettings; +} + size_t decode_packet(Codec& codec, RTPPacket& p, void* output_buffer, size_t output_capacity) { // How much data was produced @@ -399,12 +405,15 @@ size_t decode_packet(Codec& codec, RTPPacket& p, void* output_buffer, size_t out bool AudioReceiver::add(const std::shared_ptr& p, Codec** codec) { + // Estimate time length + int time_length = 0, payloadLength = p->GetPayloadLength(), ptype = p->GetPayloadType(); + // ICELogInfo(<< "Adding packet No " << p->GetSequenceNumber()); // Increase codec counter - mStat.mCodecCount[p->GetPayloadType()]++; + mStat.mCodecCount[ptype]++; // Check if codec can be handled - CodecMap::iterator codecIter = mCodecMap.find(p->GetPayloadType()); + CodecMap::iterator codecIter = mCodecMap.find(ptype); if (codecIter == mCodecMap.end()) { ICELogMedia(<< "Cannot find codec in available codecs"); @@ -427,8 +436,6 @@ bool AudioReceiver::add(const std::shared_ptr& p, Codec** co if (mStat.mCodecName.empty()) mStat.mCodecName = codecIter->second->name(); - // Estimate time length - int time_length = 0, payloadLength = p->GetPayloadLength(), ptype = p->GetPayloadType(); if (!codecIter->second->rtpLength()) time_length = codecIter->second->frameTime(); @@ -462,8 +469,11 @@ bool AudioReceiver::add(const std::shared_ptr& p, Codec** co { // Move data to packet buffer size_t available = decode_packet(**codec, *p, mDecodedFrame, sizeof mDecodedFrame); - packet->pcm().resize(available / 2); - memcpy(packet->pcm().data(), mDecodedFrame, available / 2); + if (available > 0) + { + packet->pcm().resize(available / 2); + memcpy(packet->pcm().data(), mDecodedFrame, available / 2); + } } return true; } diff --git a/src/engine/media/MT_AudioReceiver.h b/src/engine/media/MT_AudioReceiver.h index bf27d000..19f51c12 100644 --- a/src/engine/media/MT_AudioReceiver.h +++ b/src/engine/media/MT_AudioReceiver.h @@ -124,7 +124,7 @@ namespace MT // Update codec settings void setCodecSettings(const CodecList::Settings& codecSettings); - + CodecList::Settings& getCodecSettings(); // Returns false when packet is rejected as illegal. codec parameter will show codec which will be used for decoding. // Lifetime of pointer to codec is limited by lifetime of AudioReceiver (it is container). bool add(const std::shared_ptr& p, Codec** codec = nullptr); diff --git a/src/engine/media/MT_CodecList.cpp b/src/engine/media/MT_CodecList.cpp index f495c2c2..ce62bd26 100644 --- a/src/engine/media/MT_CodecList.cpp +++ b/src/engine/media/MT_CodecList.cpp @@ -25,33 +25,95 @@ using namespace MT; using strx = strx; -// ---------------- EvsSpec --------------- + +bool CodecList::Settings::contains(int ptype) const +{ + if (ptype >= 0 && ptype < 96) + return true; + + if (mAmrNbOctetPayloadType.contains(ptype)) + return true; + if (mAmrNbPayloadType.contains(ptype)) + return true; + if (mAmrWbOctetPayloadType.contains(ptype)) + return true; + if (mAmrWbPayloadType.contains(ptype)) + return true; + for (const auto& s: mOpusSpec) + if (s.mPayloadType == ptype) + return true; + for (const auto& s: mEvsSpec) + if (s.mPayloadType == ptype) + return true; + + if (mIsac16KPayloadType == ptype || mIsac32KPayloadType == ptype) + return true; + + if (mIlbc20PayloadType == ptype || mIlbc30PayloadType == ptype) + return true; + + if (mGsmEfrPayloadType == ptype || mGsmFrPayloadType == ptype || mGsmHrPayloadType == ptype) + return true; + + return false; +} std::string CodecList::Settings::toString() const { std::ostringstream oss; - oss << "wrap IuUP: " << mWrapIuUP << std::endl - << "skip decode: " << mSkipDecode << std::endl; - for (int ptype: mAmrWbPayloadType) - oss << "AMR WB ptype: " << ptype << std::endl; - for (int ptype: mAmrWbOctetPayloadType) - oss << "AMR WB octet-aligned ptype: " << ptype << std::endl; - for (int ptype: mAmrNbPayloadType) - oss << "AMR NB ptype: " << ptype << std::endl; - for (int ptype: mAmrNbOctetPayloadType) - oss << "AMR NB octet-aligned ptype:" << ptype << std::endl; + // oss << "wrap IuUP: " << mWrapIuUP << std::endl + // << "skip decode: " << mSkipDecode << std::endl; - oss << "ISAC 16Khz ptype: " << mIsac16KPayloadType << std::endl - << "ISAC 32Khz ptype: " << mIsac32KPayloadType << std::endl - << "iLBC 20ms ptype: " << mIlbc20PayloadType << std::endl - << "iLBC 30ms ptype: " << mIlbc30PayloadType << std::endl - << "GSM FR ptype: " << mGsmFrPayloadType << ", GSM FR plength: " << mGsmFrPayloadLength << std::endl - << "GSM HR ptype: " << mGsmHrPayloadType << std::endl - << "GSM EFR ptype: " << mGsmEfrPayloadType << std::endl; + if (!mAmrWbPayloadType.empty()) + { + oss << "AMR WB ptype: "; + for (int ptype: mAmrWbPayloadType) + oss << ptype << " "; + } + if (!mAmrWbOctetPayloadType.empty()) + { + oss << "AMR WB octet ptype: "; + for (int ptype: mAmrWbOctetPayloadType) + oss << ptype << " "; + } + + if (!mAmrNbPayloadType.empty()) + { + oss << "AMR ptype: "; + for (int ptype: mAmrNbPayloadType) + oss << ptype << " "; + } + + if (!mAmrNbOctetPayloadType.empty()) + { + oss << "AMR octet ptype: "; + for (int ptype: mAmrNbOctetPayloadType) + oss << ptype << " "; + } + if (mIsac16KPayloadType != -1) + oss << "ISAC 16Khz ptype: " << mIsac16KPayloadType << " "; + + if (mIsac32KPayloadType != -1) + oss << "ISAC 32Khz ptype: " << mIsac32KPayloadType << " "; + + if (mIlbc20PayloadType != -1) + oss << "iLBC 20ms ptype: " << mIlbc20PayloadType << " "; + + if (mIlbc30PayloadType != -1) + oss << "iLBC 30ms ptype: " << mIlbc30PayloadType << " "; + + if (mGsmFrPayloadType != -1) + oss << "GSM FR ptype: " << mGsmFrPayloadType << ", GSM FR plength: " << mGsmFrPayloadLength << " "; + + if (mGsmHrPayloadType != -1) + oss << "GSM HR ptype: " << mGsmHrPayloadType << " "; + + if (mGsmEfrPayloadType != -1) + oss << "GSM EFR ptype: " << mGsmEfrPayloadType << " "; for (auto& spec: mEvsSpec) { - oss << "EVS ptype: " << spec.mPayloadType << ", bw: " << spec.mBandwidth << ", enc: " << (spec.mEncodingType == EvsSpec::Encoding_MIME ? "mime" : "g192") << std::endl; + oss << "EVS ptype: " << spec.mPayloadType << ", bw: " << spec.mBandwidth << ", enc: " << (spec.mEncodingType == EvsSpec::Encoding_MIME ? "mime" : "g192") << " "; } for (auto& spec: mOpusSpec) @@ -100,24 +162,24 @@ CodecList::Settings::EvsSpec CodecList::Settings::EvsSpec::parse(const std::stri if (encoding_type == "mime") result.mEncodingType = Encoding_MIME; else - if (encoding_type == "g192") - result.mEncodingType = Encoding_G192; - else - throw std::logic_error("Bad EVS codec encoding type"); + if (encoding_type == "g192") + result.mEncodingType = Encoding_G192; + else + throw std::logic_error("Bad EVS codec encoding type"); // Bandwidth std::string& bandwidth = parts.back(); if (bandwidth == "nb" || bandwidth == "NB") result.mBandwidth = Bandwidth_NB; else - if (bandwidth == "wb" || bandwidth == "WB") - result.mBandwidth = Bandwidth_WB; - else - if (bandwidth == "swb" || bandwidth == "SWB") - result.mBandwidth = Bandwidth_SWB; - else - if (bandwidth == "fb" || bandwidth == "FB") - result.mBandwidth = Bandwidth_FB; + if (bandwidth == "wb" || bandwidth == "WB") + result.mBandwidth = Bandwidth_WB; + else + if (bandwidth == "swb" || bandwidth == "SWB") + result.mBandwidth = Bandwidth_SWB; + else + if (bandwidth == "fb" || bandwidth == "FB") + result.mBandwidth = Bandwidth_FB; } return result; @@ -145,6 +207,21 @@ CodecList::Settings::OpusSpec CodecList::Settings::OpusSpec::parse(const std::st } #if defined(USE_RESIP_INTEGRATION) +static int findOctetMode(const char* line) +{ + const char* param_name = "octet-align="; + auto p = strstr(line, param_name); + if (!p) + return 0; + + p += strlen(param_name); + char int_buf[8] = {0}; + int int_buf_offset = 0; + while (*p && isdigit(*p) && int_buf_offset < sizeof(int_buf)) + int_buf[int_buf_offset++] = *p++; + return atoi(int_buf); +} + CodecList::Settings CodecList::Settings::parseSdp(const std::list& codeclist) { CodecList::Settings r{DefaultSettings}; @@ -155,15 +232,44 @@ CodecList::Settings CodecList::Settings::parseSdp(const std::list& int samplerate = c.getRate(); int ptype = c.payloadType(); + auto enc_params = c.encodingParameters(); // This must channels number for Opus codec + auto params = c.parameters(); + // Dynamic payload type codecs only - ISAC / iLBC / Speex / etc. if (codec_name == "OPUS") { // Check the parameters - auto enc_params = c.encodingParameters(); // This must channels number for Opus codec - auto params = c.parameters(); int channels = strx::toInt(enc_params.c_str(), 1); r.mOpusSpec.push_back({ptype, samplerate, channels}); } + else + if (codec_name == "AMR-WB") + { + int octet_mode = findOctetMode(params.c_str()); + if (octet_mode != -1) + { + if (octet_mode == 0) + r.mAmrWbPayloadType.insert(ptype); + else + if (octet_mode == 1) + r.mAmrWbOctetPayloadType.insert(ptype); + } + // std::cout << "AMR-WB parameters: " << params.c_str() << ", found octet-mode: " << octet_mode << std::endl; + } + else + if (codec_name == "AMR") + { + int octet_mode = findOctetMode(params.c_str()); + if (octet_mode != -1) + { + if (octet_mode == 0) + r.mAmrWbPayloadType.insert(ptype); + else + if (octet_mode == 1) + r.mAmrWbOctetPayloadType.insert(ptype); + } + // std::cout << "AMR parameters: " << params.c_str() << ", found octet-mode: " << octet_mode << std::endl; + } } return r; } @@ -173,7 +279,7 @@ CodecList::Settings CodecList::Settings::parseSdp(const std::list& bool CodecList::Settings::operator == (const Settings& rhs) const { if (std::tie(mWrapIuUP, mSkipDecode, mIsac16KPayloadType, mIsac32KPayloadType, mIlbc20PayloadType, mIlbc30PayloadType, mGsmFrPayloadType, mGsmFrPayloadLength, mGsmEfrPayloadType, mGsmHrPayloadType) != - std::tie(rhs.mWrapIuUP, rhs.mSkipDecode, rhs.mIsac16KPayloadType, rhs.mIsac32KPayloadType, rhs.mIlbc20PayloadType, rhs.mIlbc30PayloadType, rhs.mGsmFrPayloadType, rhs.mGsmFrPayloadLength, rhs.mGsmEfrPayloadType, rhs.mGsmHrPayloadType)) + std::tie(rhs.mWrapIuUP, rhs.mSkipDecode, rhs.mIsac16KPayloadType, rhs.mIsac32KPayloadType, rhs.mIlbc20PayloadType, rhs.mIlbc30PayloadType, rhs.mGsmFrPayloadType, rhs.mGsmFrPayloadLength, rhs.mGsmEfrPayloadType, rhs.mGsmHrPayloadType)) return false; if (mAmrNbOctetPayloadType != rhs.mAmrNbOctetPayloadType) @@ -211,108 +317,99 @@ bool CodecList::Settings::operator == (const Settings& rhs) const CodecList::Settings CodecList::Settings::DefaultSettings; CodecList::CodecList(const Settings& settings) - :mSettings(settings) + :mSettings(settings) { init(mSettings); } void CodecList::init(const Settings& settings) { - for (auto f: mFactoryList) - delete f; - mFactoryList.clear(); - + mFactoryList.clear(); + mSettings = settings; #if defined(USE_OPUS_CODEC) - if (settings.mOpusSpec.empty()) - { - mFactoryList.push_back(new OpusCodec::OpusFactory(48000, 2, MT_OPUS_CODEC_PT)); - } - else - { for (auto spec: settings.mOpusSpec) { - mFactoryList.push_back(new OpusCodec::OpusFactory(spec.mRate, spec.mChannels, spec.mPayloadType)); + mFactoryList.push_back(std::make_shared(spec.mRate, spec.mChannels, spec.mPayloadType)); } - } #endif #if !defined(TARGET_ANDROID) && !defined(TARGET_OPENWRT) && !defined(TARGET_RPI) #if defined(USE_AMR_CODEC) - for (int pt: mSettings.mAmrWbPayloadType) - mFactoryList.push_back(new AmrWbCodec::CodecFactory({mSettings.mWrapIuUP, false, pt})); - for (int pt: mSettings.mAmrWbOctetPayloadType) - mFactoryList.push_back(new AmrWbCodec::CodecFactory({mSettings.mWrapIuUP, true, pt})); + for (int pt: mSettings.mAmrWbPayloadType) + mFactoryList.push_back(std::make_shared(AmrCodecConfig{mSettings.mWrapIuUP, false, pt})); + for (int pt: mSettings.mAmrWbOctetPayloadType) + mFactoryList.push_back(std::make_shared(AmrCodecConfig{mSettings.mWrapIuUP, true, pt})); - for (int pt: mSettings.mAmrNbPayloadType) - mFactoryList.push_back(new AmrNbCodec::CodecFactory({mSettings.mWrapIuUP, false, pt})); - for (int pt: mSettings.mAmrNbOctetPayloadType) - mFactoryList.push_back(new AmrNbCodec::CodecFactory({mSettings.mWrapIuUP, true, pt})); + for (int pt: mSettings.mAmrNbPayloadType) + mFactoryList.push_back(std::make_shared(AmrCodecConfig{mSettings.mWrapIuUP, false, pt})); + for (int pt: mSettings.mAmrNbOctetPayloadType) + mFactoryList.push_back(std::make_shared(AmrCodecConfig{mSettings.mWrapIuUP, true, pt})); - mFactoryList.push_back(new GsmEfrCodec::GsmEfrFactory(mSettings.mWrapIuUP, mSettings.mGsmEfrPayloadType)); + if (mSettings.mGsmEfrPayloadType != -1) + mFactoryList.push_back(std::make_shared(mSettings.mWrapIuUP, mSettings.mGsmEfrPayloadType)); #endif #endif - // mFactoryList.push_back(new IsacCodec::IsacFactory16K(mSettings.mIsac16KPayloadType)); - // mFactoryList.push_back(new IlbcCodec::IlbcFactory(mSettings.mIlbc20PayloadType, mSettings.mIlbc30PayloadType)); - mFactoryList.push_back(new G711Codec::AlawFactory()); - mFactoryList.push_back(new G711Codec::UlawFactory()); + mFactoryList.push_back(std::make_shared()); + mFactoryList.push_back(std::make_shared()); - mFactoryList.push_back(new GsmCodec::GsmFactory(mSettings.mGsmFrPayloadLength == 32 ? GsmCodec::Type::Bytes_32 : GsmCodec::Type::Bytes_33, mSettings.mGsmFrPayloadType)); - mFactoryList.push_back(new G722Codec::G722Factory()); - mFactoryList.push_back(new G729Codec::G729Factory()); + if (mSettings.mGsmFrPayloadType != -1) + mFactoryList.push_back(std::make_shared(mSettings.mGsmFrPayloadLength == 32 ? GsmCodec::Type::Bytes_32 : GsmCodec::Type::Bytes_33, mSettings.mGsmFrPayloadType)); + mFactoryList.push_back(std::make_shared()); + mFactoryList.push_back(std::make_shared()); #ifndef TARGET_ANDROID - mFactoryList.push_back(new GsmHrCodec::GsmHrFactory(mSettings.mGsmHrPayloadType)); + if (mSettings.mGsmHrPayloadType != -1) + mFactoryList.push_back(std::make_shared(mSettings.mGsmHrPayloadType)); #endif #if !defined(TARGET_ANDROID) && defined(USE_EVS_CODEC) - for (auto& spec: settings.mEvsSpec) - { - EVSCodec::StreamParameters evs_params; - evs_params.mime = spec.mEncodingType == Settings::EvsSpec::Encoding_MIME; - evs_params.bw = (int)spec.mBandwidth; - evs_params.ptime = 20; - evs_params.ptype = spec.mPayloadType; + for (auto& spec: settings.mEvsSpec) + { + EVSCodec::StreamParameters evs_params; + evs_params.mime = spec.mEncodingType == Settings::EvsSpec::Encoding_MIME; + evs_params.bw = (int)spec.mBandwidth; + evs_params.ptime = 20; + evs_params.ptype = spec.mPayloadType; - mFactoryList.push_back(new EVSCodec::EVSFactory(evs_params)); - } + mFactoryList.push_back(std::make_shared(evs_params)); + } #endif } CodecList::~CodecList() { - for (auto f: mFactoryList) - delete f; + mFactoryList.clear(); } int CodecList::count() const { - return static_cast(mFactoryList.size()); + return static_cast(mFactoryList.size()); } Codec::Factory& CodecList::codecAt(int index) const { - return *mFactoryList[static_cast(index)]; + return *mFactoryList[static_cast(index)]; } int CodecList::findCodec(const std::string &name) const { - for (int i=0; icreate(); - cm.insert({factory->payloadType(), c}); - } + cm.clear(); + 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(), c}); + } } CodecListPriority::CodecListPriority() @@ -327,55 +424,55 @@ CodecListPriority::~CodecListPriority() bool CodecListPriority::isNegativePriority(const CodecListPriority::Item& item) { - return item.mPriority < 0; + return item.mPriority < 0; } bool CodecListPriority::compare(const Item& item1, const Item& item2) { - return item1.mPriority < item2.mPriority; + return item1.mPriority < item2.mPriority; } void CodecListPriority::setupFrom(PVariantMap vmap) { - CodecList::Settings settings; - CodecList cl(settings); - //mPriorityList.resize(cl.count()); - bool emptyVmap = vmap ? vmap->empty() : true; + CodecList::Settings settings; + CodecList cl(settings); + //mPriorityList.resize(cl.count()); + bool emptyVmap = vmap ? vmap->empty() : true; - if (emptyVmap) - { - for (int i=0; iexists(i) ? vmap->at(i).asInt() : 1000; // Non listed codecs will get lower priority - mPriorityList.push_back(item); + for (int i=0; iexists(i) ? vmap->at(i).asInt() : 1000; // Non listed codecs will get lower priority + mPriorityList.push_back(item); + } + + // Remove -1 records + mPriorityList.erase(std::remove_if(mPriorityList.begin(), mPriorityList.end(), isNegativePriority), mPriorityList.end()); + + // Sort by priority + std::sort(mPriorityList.begin(), mPriorityList.end(), compare); } - - // Remove -1 records - mPriorityList.erase(std::remove_if(mPriorityList.begin(), mPriorityList.end(), isNegativePriority), mPriorityList.end()); - - // Sort by priority - std::sort(mPriorityList.begin(), mPriorityList.end(), compare); - } } int CodecListPriority::count(const CodecList & /*cl*/) const { - return static_cast(mPriorityList.size()); + return static_cast(mPriorityList.size()); } Codec::Factory& CodecListPriority::codecAt(const CodecList& cl, int index) const { - return cl.codecAt(mPriorityList[static_cast(index)].mCodecIndex); + return cl.codecAt(mPriorityList[static_cast(index)].mCodecIndex); } diff --git a/src/engine/media/MT_CodecList.h b/src/engine/media/MT_CodecList.h index 9effc42a..76b028ea 100644 --- a/src/engine/media/MT_CodecList.h +++ b/src/engine/media/MT_CodecList.h @@ -43,7 +43,7 @@ public: int mIsac32KPayloadType = -1; int mIlbc20PayloadType = -1; int mIlbc30PayloadType = -1; - int mGsmFrPayloadType = 3; // GSM is codec with fixed payload type. But sometimes it has to be overwritten. + int mGsmFrPayloadType = -1; // GSM is codec with fixed payload type. But sometimes it has to be overwritten. int mGsmFrPayloadLength = 33; // Expected GSM payload length int mGsmHrPayloadType = -1; int mGsmEfrPayloadType = -1; @@ -96,6 +96,9 @@ public: }; std::vector mOpusSpec; + // Payload type + bool contains(int ptype) const; + // Textual representation - used in logging std::string toString() const; void clear(); @@ -110,7 +113,9 @@ public: CodecList(const Settings& settings); ~CodecList(); - void setSettings(const Settings& settings) { init(settings); } + void setSettings(const Settings& settings) { + init(settings); + } int count() const; Codec::Factory& codecAt(int index) const; @@ -119,7 +124,7 @@ public: void clear(); protected: - typedef std::vector FactoryList; + typedef std::vector> FactoryList; FactoryList mFactoryList; Settings mSettings;