Commit d7377c89 authored by Tristan Matthews's avatar Tristan Matthews

* #15528: audiortp: store vector of audioCodecs

This will allow assymetric audio codec use (i.e. send with one, receive
with another).
parent 0fb514e1
......@@ -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()
......
......@@ -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
......
......@@ -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
......
......@@ -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 {
......
......@@ -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();
......
......@@ -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&);
......
......@@ -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();
}
}
......@@ -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_;
};
}
......
......@@ -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();
}
......
......@@ -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_;
......
......@@ -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());
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment