diff --git a/daemon/src/audio/audiortp/audio_rtp_factory.cpp b/daemon/src/audio/audiortp/audio_rtp_factory.cpp index 25be68841ed4df731a051fa92600d9b994347924..246aa520027ee83c3f410f7adb68aec05c3d1a10 100644 --- a/daemon/src/audio/audiortp/audio_rtp_factory.cpp +++ b/daemon/src/audio/audiortp/audio_rtp_factory.cpp @@ -120,12 +120,12 @@ void AudioRtpFactory::initSession() rtpSession_ = new AudioSymmetricRtpSession(*ca_); } -void sfl::AudioRtpFactory::start(AudioCodec* audiocodec) +void sfl::AudioRtpFactory::start(const std::vector<AudioCodec*> &audioCodecs) { if (rtpSession_ == NULL) throw AudioRtpFactoryException("RTP session was null when trying to start audio thread"); - if (rtpSession_->startRtpThread(*audiocodec) != 0) + if (rtpSession_->startRtpThread(audioCodecs) != 0) throw AudioRtpFactoryException("Failed to start AudioRtpSession thread"); } @@ -145,12 +145,12 @@ int AudioRtpFactory::getSessionMedia() return rtpSession_->getCodecPayloadType(); } -void AudioRtpFactory::updateSessionMedia(AudioCodec *audiocodec) +void AudioRtpFactory::updateSessionMedia(const std::vector<AudioCodec*> &audioCodecs) { if (rtpSession_ == NULL) throw AudioRtpFactoryException("rtpSession_ was NULL when trying to update IP address"); - rtpSession_->updateSessionMedia(*audiocodec); + rtpSession_->updateSessionMedia(audioCodecs); } void AudioRtpFactory::updateDestinationIpAddress() diff --git a/daemon/src/audio/audiortp/audio_rtp_factory.h b/daemon/src/audio/audiortp/audio_rtp_factory.h index 96cdca10fa26672ee630162f7ec1f260259f55d0..8a74067b9559ad44d4e69b96da57f6ab5b090b60 100644 --- a/daemon/src/audio/audiortp/audio_rtp_factory.h +++ b/daemon/src/audio/audiortp/audio_rtp_factory.h @@ -81,7 +81,7 @@ class AudioRtpFactory { * file. initAudioSymmetricRtpSession must have been called prior to that. * @param None */ - void start(AudioCodec*); + void start(const std::vector<AudioCodec*> &audioCodecs); /** * Stop the audio rtp thread of the type specified in the configuration @@ -98,7 +98,7 @@ class AudioRtpFactory { /** * Dynamically update session media */ - void updateSessionMedia(AudioCodec *); + void updateSessionMedia(const std::vector<AudioCodec*> &audioCodecs); /** * Update current RTP destination address with one stored in call diff --git a/daemon/src/audio/audiortp/audio_rtp_record_handler.cpp b/daemon/src/audio/audiortp/audio_rtp_record_handler.cpp index 6e96499c677339a4c45f1bb50299289bd583e558..4ab82a27c286dbc087d1edd85152ade738a2fc66 100644 --- a/daemon/src/audio/audiortp/audio_rtp_record_handler.cpp +++ b/daemon/src/audio/audiortp/audio_rtp_record_handler.cpp @@ -90,7 +90,7 @@ AudioRtpRecord::AudioRtpRecord() : callId_("") , codecSampleRate_(0) , dtmfQueue_() - , audioCodec_(0) + , audioCodecs_() , audioCodecMutex_() , codecPayloadType_(0) , hasDynamicPayloadType_(false) @@ -121,6 +121,14 @@ bool AudioRtpRecord::isDead() #endif } +void +AudioRtpRecord::deleteCodecs() +{ + for (std::vector<AudioCodec *>::iterator i = audioCodecs_.begin(); i != audioCodecs_.end(); ++i) + delete *i; + audioCodecs_.clear(); +} + AudioRtpRecord::~AudioRtpRecord() { dead_ = true; @@ -135,8 +143,7 @@ AudioRtpRecord::~AudioRtpRecord() converterDecode_ = 0; { ost::MutexLock lock(audioCodecMutex_); - delete audioCodec_; - audioCodec_ = 0; + deleteCodecs(); } #if HAVE_SPEEXDSP { @@ -160,17 +167,17 @@ AudioRtpRecordHandler::AudioRtpRecordHandler(SIPCall &call) : AudioRtpRecordHandler::~AudioRtpRecordHandler() {} -void AudioRtpRecordHandler::setRtpMedia(AudioCodec *audioCodec) +void AudioRtpRecordHandler::setRtpMedia(const std::vector<AudioCodec*> &audioCodecs) { ost::MutexLock lock(audioRtpRecord_.audioCodecMutex_); - delete audioRtpRecord_.audioCodec_; + audioRtpRecord_.deleteCodecs(); // Set varios codec info to reduce indirection - audioRtpRecord_.audioCodec_ = audioCodec; - audioRtpRecord_.codecPayloadType_ = audioCodec->getPayloadType(); - audioRtpRecord_.codecSampleRate_ = audioCodec->getClockRate(); - audioRtpRecord_.codecFrameSize_ = audioCodec->getFrameSize(); - audioRtpRecord_.hasDynamicPayloadType_ = audioCodec->hasDynamicPayload(); + audioRtpRecord_.audioCodecs_ = audioCodecs; + audioRtpRecord_.codecPayloadType_ = audioCodecs[0]->getPayloadType(); + audioRtpRecord_.codecSampleRate_ = audioCodecs[0]->getClockRate(); + audioRtpRecord_.codecFrameSize_ = audioCodecs[0]->getFrameSize(); + audioRtpRecord_.hasDynamicPayloadType_ = audioCodecs[0]->hasDynamicPayload(); } void AudioRtpRecordHandler::initBuffers() @@ -266,9 +273,13 @@ int AudioRtpRecordHandler::processDataEncode() { ost::MutexLock lock(audioRtpRecord_.audioCodecMutex_); - RETURN_IF_NULL(audioRtpRecord_.audioCodec_, 0, "Audio codec already destroyed"); + if (audioRtpRecord_.audioCodecs_.empty()) { + ERROR("Audio codecs already destroyed"); + return 0; + } + RETURN_IF_NULL(audioRtpRecord_.audioCodecs_[0], 0, "Audio codec already destroyed"); unsigned char *micDataEncoded = audioRtpRecord_.encodedData_.data(); - return audioRtpRecord_.audioCodec_->encode(micDataEncoded, out, getCodecFrameSize()); + return audioRtpRecord_.audioCodecs_[0]->encode(micDataEncoded, out, getCodecFrameSize()); } } #undef RETURN_IF_NULL @@ -283,6 +294,7 @@ void AudioRtpRecordHandler::processDataDecode(unsigned char *spkrData, size_t si if (!warningInterval_) { warningInterval_ = 250; WARN("Invalid payload type %d, expected %d", payloadType, audioRtpRecord_.codecPayloadType_); + WARN("We have %u codecs total", audioRtpRecord_.audioCodecs_.size()); } warningInterval_--; return; @@ -293,9 +305,13 @@ void AudioRtpRecordHandler::processDataDecode(unsigned char *spkrData, size_t si SFLDataFormat *spkrDataDecoded = audioRtpRecord_.decData_.data(); { ost::MutexLock lock(audioRtpRecord_.audioCodecMutex_); - RETURN_IF_NULL(audioRtpRecord_.audioCodec_, "Audio codec already destroyed"); + if (audioRtpRecord_.audioCodecs_.empty()) { + ERROR("Audio codecs already destroyed"); + return; + } + RETURN_IF_NULL(audioRtpRecord_.audioCodecs_[0], "Audio codecs already destroyed"); // Return the size of data in samples - inSamples = audioRtpRecord_.audioCodec_->decode(spkrDataDecoded, spkrData, size); + inSamples = audioRtpRecord_.audioCodecs_[0]->decode(spkrDataDecoded, spkrData, size); } #if HAVE_SPEEXDSP diff --git a/daemon/src/audio/audiortp/audio_rtp_record_handler.h b/daemon/src/audio/audiortp/audio_rtp_record_handler.h index 175f202c466bd0929c92fb3942a8c16ecd297fc0..2f35664bb2993d3e566f78b9216d9c948e4434d6 100644 --- a/daemon/src/audio/audiortp/audio_rtp_record_handler.h +++ b/daemon/src/audio/audiortp/audio_rtp_record_handler.h @@ -72,12 +72,13 @@ class AudioRtpRecord { public: AudioRtpRecord(); ~AudioRtpRecord(); + void deleteCodecs(); std::string callId_; int codecSampleRate_; std::list<DTMFEvent> dtmfQueue_; private: - AudioCodec *audioCodec_; + std::vector<AudioCodec*> audioCodecs_; ost::Mutex audioCodecMutex_; int codecPayloadType_; bool hasDynamicPayloadType_; @@ -122,10 +123,10 @@ class AudioRtpRecordHandler { /** * Set rtp media for this session */ - void setRtpMedia(AudioCodec* audioCodec); + void setRtpMedia(const std::vector<AudioCodec*> &audioCodec); AudioCodec *getAudioCodec() const { - return audioRtpRecord_.audioCodec_; + return audioRtpRecord_.audioCodecs_[0]; } int getCodecPayloadType() const { diff --git a/daemon/src/audio/audiortp/audio_rtp_session.cpp b/daemon/src/audio/audiortp/audio_rtp_session.cpp index 9a960a0b5f11fb208914cc2e0d5f1623af08db3f..a33811f491937d5e0272e172c7e0d1e371316db2 100644 --- a/daemon/src/audio/audiortp/audio_rtp_session.cpp +++ b/daemon/src/audio/audiortp/audio_rtp_session.cpp @@ -61,11 +61,11 @@ AudioRtpSession::~AudioRtpSession() queue_.disableStack(); } -void AudioRtpSession::updateSessionMedia(AudioCodec &audioCodec) +void AudioRtpSession::updateSessionMedia(const std::vector<AudioCodec*> &audioCodecs) { int lastSamplingRate = audioRtpRecord_.codecSampleRate_; - setSessionMedia(audioCodec); + setSessionMedia(audioCodecs); Manager::instance().audioSamplingRateChanged(audioRtpRecord_.codecSampleRate_); @@ -78,9 +78,9 @@ void AudioRtpSession::updateSessionMedia(AudioCodec &audioCodec) #endif } -void AudioRtpSession::setSessionMedia(AudioCodec &audioCodec) +void AudioRtpSession::setSessionMedia(const std::vector<AudioCodec*> &audioCodecs) { - setRtpMedia(&audioCodec); + setRtpMedia(audioCodecs); // G722 requires timestamp to be incremented at 8kHz const ost::PayloadType payloadType = getCodecPayloadType(); @@ -231,7 +231,7 @@ void AudioRtpSession::updateDestinationIpAddress() } -int AudioRtpSession::startRtpThread(AudioCodec &audiocodec) +int AudioRtpSession::startRtpThread(const std::vector<AudioCodec*> &audioCodecs) { if (isStarted_) return 0; @@ -240,7 +240,7 @@ int AudioRtpSession::startRtpThread(AudioCodec &audiocodec) isStarted_ = true; setSessionTimeouts(); - setSessionMedia(audiocodec); + setSessionMedia(audioCodecs); initBuffers(); #if HAVE_SPEEXDSP initNoiseSuppress(); diff --git a/daemon/src/audio/audiortp/audio_rtp_session.h b/daemon/src/audio/audiortp/audio_rtp_session.h index 3b2ab5975a2d521e3a7c0a355d7e00888e4c8166..fdf40d027ee35d672aebcf3f9ef8e3533a1985db 100644 --- a/daemon/src/audio/audiortp/audio_rtp_session.h +++ b/daemon/src/audio/audiortp/audio_rtp_session.h @@ -57,9 +57,9 @@ class AudioRtpSession : public AudioRtpRecordHandler { AudioRtpSession(SIPCall &sipcall, ost::RTPDataQueue &queue, ost::Thread &thread); virtual ~AudioRtpSession(); - void updateSessionMedia(AudioCodec &audioCodec); + void updateSessionMedia(const std::vector<AudioCodec*> &audioCodecs); - virtual int startRtpThread(AudioCodec&); + virtual int startRtpThread(const std::vector<AudioCodec*> &audioCodecs); /** * Used mostly when receiving a reinvite @@ -80,7 +80,7 @@ class AudioRtpSession : public AudioRtpRecordHandler { /** * Set the audio codec for this RTP session */ - void setSessionMedia(AudioCodec &codec); + void setSessionMedia(const std::vector<AudioCodec*> &codec); bool onRTPPacketRecv(ost::IncomingRTPPkt&); diff --git a/daemon/src/audio/audiortp/audio_symmetric_rtp_session.cpp b/daemon/src/audio/audiortp/audio_symmetric_rtp_session.cpp index ddf51f96c01af9ba7c9d67dd10f342da6399a90d..8eabee4a3432d0091dbfab906a516a56d242bcd6 100644 --- a/daemon/src/audio/audiortp/audio_symmetric_rtp_session.cpp +++ b/daemon/src/audio/audiortp/audio_symmetric_rtp_session.cpp @@ -43,7 +43,7 @@ AudioSymmetricRtpSession::AudioSymmetricRtpSession(SIPCall &call) : , ost::SymmetricRTPSession(ost::InetHostAddress(call.getLocalIp().c_str()), call.getLocalAudioPort()) , AudioRtpSession(call, *this, *this) , rtpThread_(*this) - , audiocodec_(0) + , audioCodecs_() { DEBUG("Setting new RTP session with destination %s:%d", call_.getLocalIp().c_str(), call_.getLocalAudioPort()); @@ -78,14 +78,14 @@ void AudioSymmetricRtpSession::AudioRtpThread::run() } } -int AudioSymmetricRtpSession::startRtpThread(AudioCodec &audiocodec) +int AudioSymmetricRtpSession::startRtpThread(const std::vector<AudioCodec*> &audioCodecs) { DEBUG("Starting main thread"); if (isStarted_) return 0; - audiocodec_ = &audiocodec; - AudioRtpSession::startRtpThread(audiocodec); + audioCodecs_ = audioCodecs; + AudioRtpSession::startRtpThread(audioCodecs); return startSymmetricRtpThread(); } } diff --git a/daemon/src/audio/audiortp/audio_symmetric_rtp_session.h b/daemon/src/audio/audiortp/audio_symmetric_rtp_session.h index 96c7e9e7d7111d728ac284624e968fdea4ad9983..030440f46d669b87a260685a7d8598c950011ac2 100644 --- a/daemon/src/audio/audiortp/audio_symmetric_rtp_session.h +++ b/daemon/src/audio/audiortp/audio_symmetric_rtp_session.h @@ -96,10 +96,10 @@ class AudioSymmetricRtpSession : public ost::TimerPort, public ost::SymmetricRTP NON_COPYABLE(AudioRtpThread); AudioSymmetricRtpSession &rtpSession_; }; - int startRtpThread(AudioCodec &audiocodec); + int startRtpThread(const std::vector<AudioCodec*> &audioCodecs); AudioRtpThread rtpThread_ ; - sfl::AudioCodec* audiocodec_; + std::vector<sfl::AudioCodec*> audioCodecs_; }; } diff --git a/daemon/src/audio/audiortp/audio_zrtp_session.cpp b/daemon/src/audio/audiortp/audio_zrtp_session.cpp index 722f845022122a3e19287fc8bd2314e987f77256..4e0c584f56ce51b37f1cb33a2a23f6640d152063 100644 --- a/daemon/src/audio/audiortp/audio_zrtp_session.cpp +++ b/daemon/src/audio/audiortp/audio_zrtp_session.cpp @@ -150,12 +150,12 @@ int AudioZrtpSession::getIncrementForDTMF() const return 160; } -int AudioZrtpSession::startRtpThread(AudioCodec &audiocodec) +int AudioZrtpSession::startRtpThread(const std::vector<AudioCodec*> &audioCodecs) { if(isStarted_) return 0; - AudioRtpSession::startRtpThread(audiocodec); + AudioRtpSession::startRtpThread(audioCodecs); return startZrtpThread(); } diff --git a/daemon/src/audio/audiortp/audio_zrtp_session.h b/daemon/src/audio/audiortp/audio_zrtp_session.h index eea68a0c5d0c322ce4668aad5ec2d33ad87111e5..a4aa98263c54b32b95351230d2c6a38cad9056c8 100644 --- a/daemon/src/audio/audiortp/audio_zrtp_session.h +++ b/daemon/src/audio/audiortp/audio_zrtp_session.h @@ -96,7 +96,7 @@ class AudioZrtpSession : void sendMicData(); void initializeZid(); std::string zidFilename_; - int startRtpThread(AudioCodec &audiocodec); + int startRtpThread(const std::vector<AudioCodec*> &audioCodecs); virtual int getIncrementForDTMF() const; AudioZrtpThread rtpThread_; diff --git a/daemon/src/sip/sipvoiplink.cpp b/daemon/src/sip/sipvoiplink.cpp index f97b9eabd68a0f971a1111acdeb143bd2f0cfd38..72f9fc4aa0024e01bf58ba5bbd03e9ae64d7db9e 100644 --- a/daemon/src/sip/sipvoiplink.cpp +++ b/daemon/src/sip/sipvoiplink.cpp @@ -341,7 +341,9 @@ pj_bool_t transaction_request_cb(pjsip_rx_data *rdata) delete call; return PJ_FALSE; } - call->getAudioRtp().start(ac); + std::vector<sfl::AudioCodec *> audioCodecs; + audioCodecs.push_back(ac); + call->getAudioRtp().start(audioCodecs); pjsip_dialog *dialog = 0; @@ -807,12 +809,15 @@ Call *SIPVoIPLink::SIPNewIpToIpCall(const std::string& id, const std::string& to delete call; throw VoipLinkException("Could not instantiate codec"); } + std::vector<sfl::AudioCodec *> audioCodecs; + audioCodecs.push_back(ac); + // Audio Rtp Session must be initialized before creating initial offer in SDP session // since SDES require crypto attribute. call->getAudioRtp().initConfig(); call->getAudioRtp().initSession(); call->getAudioRtp().initLocalCryptoInfo(); - call->getAudioRtp().start(ac); + call->getAudioRtp().start(audioCodecs); // Building the local SDP offer Sdp *localSDP = call->getLocalSDP(); @@ -865,12 +870,14 @@ Call *SIPVoIPLink::newRegisteredAccountCall(const std::string& id, const std::st delete call; throw VoipLinkException("Could not instantiate codec for early media"); } + std::vector<sfl::AudioCodec *> audioCodecs; + audioCodecs.push_back(ac); try { call->getAudioRtp().initConfig(); call->getAudioRtp().initSession(); call->getAudioRtp().initLocalCryptoInfo(); - call->getAudioRtp().start(ac); + call->getAudioRtp().start(audioCodecs); } catch (...) { delete call; throw VoipLinkException("Could not start rtp session for early media"); @@ -1034,11 +1041,14 @@ SIPVoIPLink::offhold(const std::string& id) if (ac == NULL) throw VoipLinkException("Could not instantiate codec"); + std::vector<sfl::AudioCodec *> audioCodecs; + audioCodecs.push_back(ac); + call->getAudioRtp().initConfig(); call->getAudioRtp().initSession(); call->getAudioRtp().restoreLocalContext(); call->getAudioRtp().initLocalCryptoInfoOnOffHold(); - call->getAudioRtp().start(ac); + call->getAudioRtp().start(audioCodecs); } catch (const SdpException &e) { ERROR("%s", e.what()); } catch (...) { @@ -1756,7 +1766,9 @@ void sdp_media_update_cb(pjsip_inv_session *inv, pj_status_t status) sfl::AudioCodec *ac = Manager::instance().audioCodecFactory.instantiateCodec(pl); if (!ac) throw std::runtime_error("Could not instantiate codec"); - call->getAudioRtp().updateSessionMedia(ac); + std::vector<AudioCodec*> audioCodecs; + audioCodecs.push_back(ac); + call->getAudioRtp().updateSessionMedia(audioCodecs); } } catch (const SdpException &e) { ERROR("%s", e.what());