Commit 9eebb2d1 authored by Éloi Bail's avatar Éloi Bail Committed by Adrien Béraud

daemon: manage properly hold on and hold off

Status:

* Hold on/off from Ring account work fine
* Hold on from polycom works fine
* Hold off from polycom does not restart the stream
  - Hold off lead to a re-invite (switch from PCMA to G722)
  - codec selection from PCMA to G722 is correct
  - Libav encoder switch correctly to G722
  - Libav decoder blocks in av_codec_find_stream_info

Refs #67275

Change-Id: I9c95cdb6e35934583702d9ae697926283251e5ac
parent 7396949b
......@@ -580,7 +580,7 @@ Account::desactivateAllMedia(MediaType mediaType)
}
std::vector<std::shared_ptr<AccountCodecInfo>>
Account::getActiveAccountCodecInfoList(MediaType mediaType)
Account::getActiveAccountCodecInfoList(MediaType mediaType) const
{
std::vector<std::shared_ptr<AccountCodecInfo>> accountCodecList;
for (auto& codecIt: accountCodecInfoList_) {
......
......@@ -209,6 +209,8 @@ class Account : public Serializable, public std::enable_shared_from_this<Account
void setActiveCodecs(const std::vector<unsigned>& list);
std::shared_ptr<AccountCodecInfo> searchCodecById(unsigned codecId, MediaType mediaType);
std::vector<unsigned> getActiveAccountCodecInfoIdList(MediaType mediaType) const;
std::vector<std::shared_ptr<AccountCodecInfo>> getActiveAccountCodecInfoList(MediaType mediaType) const;
std::shared_ptr<AccountCodecInfo> searchCodecByPayload(unsigned payload, MediaType mediaType);
std::string getRingtonePath() const {
......@@ -410,10 +412,8 @@ class Account : public Serializable, public std::enable_shared_from_this<Account
* private account codec searching functions
*/
std::shared_ptr<AccountCodecInfo> searchCodecByName(std::string name, MediaType mediaType);
std::shared_ptr<AccountCodecInfo> searchCodecByPayload(unsigned payload, MediaType mediaType);
std::vector<unsigned> getAccountCodecInfoIdList(MediaType mediaType) const;
void desactivateAllMedia(MediaType mediaType);
std::vector<std::shared_ptr<AccountCodecInfo>> getActiveAccountCodecInfoList(MediaType mediaType);
};
......
......@@ -156,12 +156,13 @@ IAXVoIPLink::sendAudioFromMic()
continue;
int codecType = currentCall->getAudioCodecPayload();
auto codec = getSystemCodecContainer()->searchCodecByPayload(codecType, MEDIA_AUDIO);
auto audioCodec = std::static_pointer_cast<SystemAudioCodecInfo>(codec);
if (!audioCodec)
auto codec = account_.searchCodecByPayload(codecType, MEDIA_AUDIO);
auto accountAudioCodec = std::static_pointer_cast<AccountAudioCodecInfo>(codec);
if (!accountAudioCodec)
continue;
Manager::instance().getRingBufferPool().setInternalSamplingRate(audioCodec->sampleRate);
Manager::instance().getRingBufferPool().setInternalSamplingRate(accountAudioCodec->audioformat.sample_rate);
unsigned int mainBufferSampleRate = Manager::instance().getRingBufferPool().getInternalSamplingRate();
......@@ -177,7 +178,7 @@ IAXVoIPLink::sendAudioFromMic()
samples = Manager::instance().getRingBufferPool().getData(rawBuffer_, currentCall->getCallId());
int compSize = 0;
unsigned int audioRate = audioCodec->sampleRate;
unsigned int audioRate = accountAudioCodec->audioformat.sample_rate;
int outSamples;
UNUSED AudioBuffer *in;
......@@ -341,19 +342,19 @@ IAXVoIPLink::iaxHandleVoiceEvent(iax_event* event, IAXCall& call)
if (!event->datalen)
return;
auto codec = getSystemCodecContainer()->searchCodecByPayload(call.getAudioCodecPayload(), MEDIA_AUDIO);
auto audioCodec = std::dynamic_pointer_cast<SystemAudioCodecInfo>(codec);
if (!audioCodec)
auto codec = account_.searchCodecByPayload(call.getAudioCodecPayload(), MEDIA_AUDIO);
auto accountAudioCodec = std::static_pointer_cast<AccountAudioCodecInfo>(codec);
if (!accountAudioCodec)
return;
Manager::instance().getRingBufferPool().setInternalSamplingRate(audioCodec->sampleRate);
Manager::instance().getRingBufferPool().setInternalSamplingRate(accountAudioCodec->audioformat.sample_rate);
unsigned int mainBufferSampleRate = Manager::instance().getRingBufferPool().getInternalSamplingRate();
if (event->subclass)
call.format = event->subclass;
unsigned int size = event->datalen;
unsigned int max = audioCodec->sampleRate * 20 / 1000;
unsigned int max = accountAudioCodec->audioformat.sample_rate * 20 / 1000;
if (size > max)
size = max;
......@@ -369,7 +370,7 @@ IAXVoIPLink::iaxHandleVoiceEvent(iax_event* event, IAXCall& call)
audioCodec->decode(rawBuffer_.getData(), data , size);
#endif
AudioBuffer *out = &rawBuffer_;
unsigned int audioRate = audioCodec->sampleRate;
unsigned int audioRate = accountAudioCodec->audioformat.sample_rate;
if (audioRate != mainBufferSampleRate) {
rawBuffer_.setSampleRate(mainBufferSampleRate);
......
......@@ -652,6 +652,9 @@ ManagerImpl::offHoldCall(const std::string& callId)
if (hasCurrentCall()) {
if (not isConference(currentCallId) and not isConferenceParticipant(currentCallId)) {
RING_DBG("Has current call (%s), put on hold", currentCallId.c_str());
//FIXME: ebail
// if 2 consecutive offHoldCall done, the second one should be ignored (already offhold)
// this call put the call onHold
onHoldCall(currentCallId);
} else if (isConference(currentCallId) && callId != currentCallId) {
holdConference(currentCallId);
......
......@@ -149,8 +149,9 @@ AudioSender::process()
// FIXME
AudioBuffer micData(samplesToGet, mainBuffFormat);
auto accountAudioCodec = std::static_pointer_cast<AccountAudioCodecInfo>(args_.codec);
const auto samples = Manager::instance().getRingBufferPool().getData(micData, id_);
micData.setChannelNum(args_.audioformat.nb_channels, true); // down/upmix as needed
micData.setChannelNum(accountAudioCodec->audioformat.nb_channels, true); // down/upmix as needed
if (samples != samplesToGet) {
RING_ERR("Asked for %d samples from bindings on call '%s', got %d",
......@@ -158,12 +159,12 @@ AudioSender::process()
return;
}
if (mainBuffFormat.sample_rate != args_.audioformat.sample_rate) {
if (mainBuffFormat.sample_rate != accountAudioCodec->audioformat.sample_rate) {
if (not resampler_) {
RING_DBG("Creating audio resampler");
resampler_.reset(new Resampler(args_.audioformat));
resampler_.reset(new Resampler(accountAudioCodec->audioformat));
}
AudioBuffer resampledData(samplesToGet, args_.audioformat);
AudioBuffer resampledData(samplesToGet, accountAudioCodec->audioformat);
resampler_->resample(micData, resampledData);
if (audioEncoder_->encode_audio(resampledData) < 0)
RING_ERR("encoding failed");
......@@ -392,7 +393,8 @@ AudioRtpSession::startReceiver()
if (receiveThread_)
RING_WARN("Restarting audio receiver");
receiveThread_.reset(new AudioReceiveThread(callID_, remote_.audioformat,
auto accountAudioCodec = std::static_pointer_cast<AccountAudioCodecInfo>(remote_.codec);
receiveThread_.reset(new AudioReceiveThread(callID_, accountAudioCodec->audioformat,
remote_.receiving_sdp));
receiveThread_->addIOContext(*socketPair_);
receiveThread_->startLoop();
......@@ -404,8 +406,8 @@ AudioRtpSession::start()
std::lock_guard<std::recursive_mutex> lock(mutex_);
if (not local_.enabled and not remote_.enabled) {
stop();
return;
stop();
return;
}
try {
......
......@@ -90,18 +90,12 @@ SystemAudioCodecInfo::SystemAudioCodecInfo(unsigned m_avcodecId,
unsigned m_nbChannels,
unsigned m_payloadType)
: SystemCodecInfo(m_avcodecId, m_name, m_libName, MEDIA_AUDIO, m_type, m_bitrate, m_payloadType)
, sampleRate(m_sampleRate), nbChannels(m_nbChannels)
, audioformat{m_sampleRate, m_nbChannels}
{}
SystemAudioCodecInfo::~SystemAudioCodecInfo()
{}
bool
SystemAudioCodecInfo::isPCMG722() const
{
return avcodecId == AV_CODEC_ID_ADPCM_G722;
}
std::map<std::string, std::string>
SystemAudioCodecInfo::getCodecSpecifications()
......@@ -110,8 +104,8 @@ SystemAudioCodecInfo::getCodecSpecifications()
{DRing::Account::ConfProperties::CodecInfo::NAME, name},
{DRing::Account::ConfProperties::CodecInfo::TYPE, (mediaType & MEDIA_AUDIO ? "AUDIO" : "VIDEO")},
{DRing::Account::ConfProperties::CodecInfo::BITRATE, std::to_string(bitrate)},
{DRing::Account::ConfProperties::CodecInfo::SAMPLE_RATE, std::to_string(sampleRate)},
{DRing::Account::ConfProperties::CodecInfo::CHANNEL_NUMBER, std::to_string(nbChannels)}
{DRing::Account::ConfProperties::CodecInfo::SAMPLE_RATE, std::to_string(audioformat.sample_rate)},
{DRing::Account::ConfProperties::CodecInfo::CHANNEL_NUMBER, std::to_string(audioformat.nb_channels)}
};
}
......@@ -156,8 +150,7 @@ AccountCodecInfo::~AccountCodecInfo()
AccountAudioCodecInfo::AccountAudioCodecInfo(const SystemAudioCodecInfo& sysCodecInfo)
: AccountCodecInfo(sysCodecInfo)
, sampleRate(sysCodecInfo.sampleRate)
, nbChannels(sysCodecInfo.nbChannels)
, audioformat{sysCodecInfo.audioformat}
{}
std::map<std::string, std::string>
......@@ -167,11 +160,18 @@ AccountAudioCodecInfo::getCodecSpecifications()
{DRing::Account::ConfProperties::CodecInfo::NAME, systemCodecInfo.name},
{DRing::Account::ConfProperties::CodecInfo::TYPE, (systemCodecInfo.mediaType & MEDIA_AUDIO ? "AUDIO" : "VIDEO")},
{DRing::Account::ConfProperties::CodecInfo::BITRATE, std::to_string(bitrate)},
{DRing::Account::ConfProperties::CodecInfo::SAMPLE_RATE, std::to_string(sampleRate)},
{DRing::Account::ConfProperties::CodecInfo::CHANNEL_NUMBER, std::to_string(nbChannels)}
{DRing::Account::ConfProperties::CodecInfo::SAMPLE_RATE, std::to_string(audioformat.sample_rate)},
{DRing::Account::ConfProperties::CodecInfo::CHANNEL_NUMBER, std::to_string(audioformat.nb_channels)}
};
}
bool
AccountAudioCodecInfo::isPCMG722() const
{
return systemCodecInfo.avcodecId == AV_CODEC_ID_ADPCM_G722;
}
AccountAudioCodecInfo::~AccountAudioCodecInfo()
{}
......
......@@ -103,10 +103,8 @@ struct SystemAudioCodecInfo : SystemCodecInfo
~SystemAudioCodecInfo();
std::map<std::string, std::string> getCodecSpecifications();
bool isPCMG722() const;
unsigned sampleRate;
unsigned nbChannels;
AudioFormat audioformat {AudioFormat::NONE()};
};
/*
......@@ -156,8 +154,8 @@ struct AccountAudioCodecInfo : AccountCodecInfo
std::map<std::string, std::string> getCodecSpecifications();
/* account custom values */
unsigned sampleRate;
unsigned nbChannels;
AudioFormat audioformat {AudioFormat::NONE()};
bool isPCMG722() const;
};
struct AccountVideoCodecInfo : AccountCodecInfo
......@@ -247,16 +245,17 @@ struct MediaDescription {
IpAddr addr {};
/** Codec */
std::shared_ptr<SystemCodecInfo> codec {};
std::shared_ptr<AccountCodecInfo> codec {};
std::string payload_type {};
std::string receiving_sdp {};
unsigned bitrate {};
/** Audio parameters */
AudioFormat audioformat {AudioFormat::NONE()};
unsigned frame_size {};
/** Video parameters */
//TODO: ebail manage it in AccountVideoCodecInfo
std::string parameters {};
/** Crypto parameters */
......
......@@ -136,6 +136,7 @@ int MediaDecoder::setupFromAudioData(const AudioFormat format)
#else
ret = avformat_find_stream_info(inputCtx_, NULL);
#endif
RING_DBG("Finding stream info DONE");
if (ret < 0) {
// workaround for this bug:
......
......@@ -81,17 +81,18 @@ void MediaEncoder::setOptions(const MediaDescription& args)
{
av_dict_set(&options_, "bitrate", ring::to_string(args.bitrate).c_str(), 0);
if (args.audioformat.sample_rate)
auto accountAudioCodec = std::static_pointer_cast<AccountAudioCodecInfo>(args.codec);
if (accountAudioCodec->audioformat.sample_rate)
av_dict_set(&options_, "sample_rate",
ring::to_string(args.audioformat.sample_rate).c_str(), 0);
ring::to_string(accountAudioCodec->audioformat.sample_rate).c_str(), 0);
if (args.audioformat.nb_channels)
if (accountAudioCodec->audioformat.nb_channels)
av_dict_set(&options_, "channels",
ring::to_string(args.audioformat.nb_channels).c_str(), 0);
ring::to_string(accountAudioCodec->audioformat.nb_channels).c_str(), 0);
if (args.audioformat.sample_rate && args.audioformat.nb_channels)
if (accountAudioCodec->audioformat.sample_rate && accountAudioCodec->audioformat.nb_channels)
av_dict_set(&options_, "frame_size",
ring::to_string(static_cast<unsigned>(0.02 * args.audioformat.sample_rate)).c_str(), 0);
ring::to_string(static_cast<unsigned>(0.02 * accountAudioCodec->audioformat.sample_rate)).c_str(), 0);
if (not args.payload_type.empty())
av_dict_set(&options_, "payload_type", args.payload_type.c_str(), 0);
......@@ -118,23 +119,26 @@ MediaEncoder::openOutput(const char *filename,
outputCtx_->filename[sizeof(outputCtx_->filename) - 1] = '\0';
/* find the video encoder */
outputEncoder_ = avcodec_find_encoder((AVCodecID)args.codec->avcodecId);
outputEncoder_ = avcodec_find_encoder((AVCodecID)args.codec->systemCodecInfo.avcodecId);
if (!outputEncoder_) {
RING_ERR("Encoder \"%s\" not found!", args.codec->name.c_str());
RING_ERR("Encoder \"%s\" not found!", args.codec->systemCodecInfo.name.c_str());
throw MediaEncoderException("No output encoder");
}
prepareEncoderContext(args.type == MEDIA_VIDEO);
prepareEncoderContext(args.codec->systemCodecInfo.mediaType == MEDIA_VIDEO);
/* let x264 preset override our encoder settings */
if (args.codec->avcodecId == AV_CODEC_ID_H264) {
if (args.codec->systemCodecInfo.avcodecId == AV_CODEC_ID_H264) {
//AVDictionaryEntry *entry = av_dict_get(options_, "parameters", NULL, 0);
// FIXME: this should be parsed from the fmtp:profile-level-id
// attribute of our peer, it will determine what profile and
// level we are sending (i.e. that they can accept).
extractProfileLevelID(args.parameters/*entry?entry->value:""*/, encoderCtx_);
auto systemVideoCodecInfo =
dynamic_cast<const SystemVideoCodecInfo&> (args.codec->systemCodecInfo);
extractProfileLevelID(systemVideoCodecInfo.parameters/*entry?entry->value:""*/, encoderCtx_);
forcePresetX264();
} else if (args.codec->avcodecId == AV_CODEC_ID_VP8) {
} else if (args.codec->systemCodecInfo.avcodecId == AV_CODEC_ID_VP8) {
av_opt_set(encoderCtx_->priv_data, "quality", "realtime", 0);
}
......@@ -158,7 +162,7 @@ MediaEncoder::openOutput(const char *filename,
stream_->codec = encoderCtx_;
#ifdef RING_VIDEO
if (args.type == MEDIA_VIDEO) {
if (args.codec->systemCodecInfo.mediaType == MEDIA_VIDEO) {
// allocate buffers for both scaled (pre-encoder) and encoded frames
const int width = encoderCtx_->width;
const int height = encoderCtx_->height;
......
......@@ -274,8 +274,8 @@ RingAccount::createOutgoingCall(const std::shared_ptr<SIPCall>& call, const std:
sdp.setPublishedIP(addrSdp);
const bool created = sdp.createOffer(
getActiveAccountCodecInfoIdList(MEDIA_AUDIO),
getActiveAccountCodecInfoIdList(MEDIA_VIDEO),
getActiveAccountCodecInfoList(MEDIA_AUDIO),
getActiveAccountCodecInfoList(MEDIA_VIDEO),
getSrtpKeyExchange()
);
......
This diff is collapsed.
......@@ -126,8 +126,8 @@ class Sdp {
* SDP negotiator instance with it.
* @returns true if offer was created, false otherwise
*/
bool createOffer(const std::vector<unsigned>& selectedAudioCodecs,
const std::vector<unsigned>& selectedVideoCodecs,
bool createOffer(const std::vector<std::shared_ptr<AccountCodecInfo>>& selectedAudioCodecs,
const std::vector<std::shared_ptr<AccountCodecInfo>>& selectedVideoCodecs,
sip_utils::KeyExchangeProtocol);
/*
......@@ -137,8 +137,8 @@ class Sdp {
* @param remote The remote offer
*/
void receiveOffer(const pjmedia_sdp_session* remote,
const std::vector<unsigned>& selectedAudioCodecs,
const std::vector<unsigned>& selectedVideoCodecs,
const std::vector<std::shared_ptr<AccountCodecInfo>>& selectedAudioCodecs,
const std::vector<std::shared_ptr<AccountCodecInfo>>& selectedVideoCodecs,
sip_utils::KeyExchangeProtocol);
/**
......@@ -283,14 +283,14 @@ class Sdp {
/**
* Codec Map used for offer
*/
std::vector<std::shared_ptr<SystemAudioCodecInfo>> audio_codec_list_;
std::vector<std::shared_ptr<SystemVideoCodecInfo>> video_codec_list_;
std::vector<std::shared_ptr<AccountCodecInfo>> audio_codec_list_;
std::vector<std::shared_ptr<AccountCodecInfo>> video_codec_list_;
/**
* The codecs that will be used by the session (after the SDP negotiation)
*/
std::vector<std::shared_ptr<SystemAudioCodecInfo>> sessionAudioMediaLocal_;
std::vector<std::shared_ptr<SystemAudioCodecInfo>> sessionAudioMediaRemote_;
std::vector<std::shared_ptr<AccountAudioCodecInfo>> sessionAudioMediaLocal_;
std::vector<std::shared_ptr<AccountAudioCodecInfo>> sessionAudioMediaRemote_;
std::vector<std::string> sessionVideoMedia_;
std::string publishedIpAddr_;
......@@ -319,14 +319,14 @@ class Sdp {
* Build the local media capabilities for this session
* @param List of codec in preference order
*/
void setLocalMediaAudioCapabilities(const std::vector<unsigned>& selected);
void setLocalMediaVideoCapabilities(const std::vector<unsigned>& codecs);
void setLocalMediaAudioCapabilities(const std::vector<std::shared_ptr<AccountCodecInfo>>& selectedAudioCodecs);
void setLocalMediaVideoCapabilities(const std::vector<std::shared_ptr<AccountCodecInfo>>& selectedVideoCodecs);
/*
* Build the local SDP offer
*/
int createLocalSession(const std::vector<unsigned>& selectedAudio,
const std::vector<unsigned>& selectedVideo,
int createLocalSession(const std::vector<std::shared_ptr<AccountCodecInfo>>& selectedAudioCodecs,
const std::vector<std::shared_ptr<AccountCodecInfo>>& selectedVideoCodecs,
sip_utils::KeyExchangeProtocol);
/*
* Adds a sdes attribute to the given media section.
......@@ -349,6 +349,9 @@ class Sdp {
void addZrtpAttribute(pjmedia_sdp_media* media, std::string hash);
void addRTCPAttribute(pjmedia_sdp_media *med);
std::shared_ptr<AccountCodecInfo> findCodecByPayload(const unsigned payloadType);
std::shared_ptr<AccountCodecInfo> findCodecByName(const std::string &codec) const;
};
} // namespace ring
......
......@@ -262,8 +262,8 @@ SIPAccount::newOutgoingCall(const std::string& toUrl)
sdp.setPublishedIP(getPublishedAddress());
const bool created = sdp.createOffer(
getActiveAccountCodecInfoIdList(MEDIA_AUDIO),
getActiveAccountCodecInfoIdList(MEDIA_VIDEO),
getActiveAccountCodecInfoList(MEDIA_AUDIO),
getActiveAccountCodecInfoList(MEDIA_VIDEO),
getSrtpKeyExchange()
);
......
......@@ -749,6 +749,17 @@ SIPCall::startAllMedia()
RING_ERR("Inconsistent media types between local and remote for SDP media slot");
continue;
}
if (!local.codec) {
RING_ERR("No codec defined in local media slot");
continue;
}
if (!remote.codec) {
RING_ERR("No codec defined in remote media slot");
continue;
}
if (isSecure() && (not local.crypto || not remote.crypto)) {
RING_ERR("Can't perform secure call over insecure RTP transport");
continue;
......@@ -756,6 +767,34 @@ SIPCall::startAllMedia()
RtpSession* rtp = local.type == MEDIA_AUDIO
? static_cast<RtpSession*>(avformatrtp_.get())
: static_cast<RtpSession*>(&videortp_);
auto accountAudioCodec = std::static_pointer_cast<AccountAudioCodecInfo>(local.codec);
RING_DBG("########## UPDATE MEDIA ############");
RING_DBG("[LOCAL][codec:%s][enabled:%s][holding:%s]"
, local.codec->systemCodecInfo.to_string().c_str()
, local.enabled ? "true" : "false"
, local.holding ? "true" : "false"
);
RING_DBG("[LOCAL][Audioformat] [sampleRate%d][nbChanels:%d]"
, accountAudioCodec->audioformat.sample_rate
, accountAudioCodec->audioformat.nb_channels
);
RING_DBG("[LOCAL] SDP: \n %s", local.receiving_sdp.c_str());
accountAudioCodec = std::static_pointer_cast<AccountAudioCodecInfo>(remote.codec);
RING_DBG("[REMOTE][codec:%s][enabled:%s][holding:%s]"
, remote.codec->systemCodecInfo.to_string().c_str()
, remote.enabled ? "true" : "false"
, remote.holding ? "true" : "false"
);
RING_DBG("[REMOTE][Audioformat] [sampleRate%d][nbChanels:%d]"
, accountAudioCodec->audioformat.sample_rate
, accountAudioCodec->audioformat.nb_channels
);
RING_DBG("[REMOTE] SDP: \n %s", remote.receiving_sdp.c_str());
RING_DBG("####################################");
rtp->updateMedia(local, remote);
if (isIceRunning()) {
rtp->start(newIceSocket(ice_comp_id + 0),
......
......@@ -343,8 +343,8 @@ transaction_request_cb(pjsip_rx_data *rdata)
call->updateSDPFromSTUN();
call->getSDP().receiveOffer(r_sdp,
account->getActiveAccountCodecInfoIdList(MEDIA_AUDIO),
account->getActiveAccountCodecInfoIdList(MEDIA_VIDEO),
account->getActiveAccountCodecInfoList(MEDIA_AUDIO),
account->getActiveAccountCodecInfoList(MEDIA_VIDEO),
account->getSrtpKeyExchange()
);
if (not call->getIceTransport()) {
......@@ -880,8 +880,8 @@ sdp_request_offer_cb(pjsip_inv_session *inv, const pjmedia_sdp_session *offer)
auto& localSDP = call->getSDP();
localSDP.receiveOffer(offer,
account.getActiveAccountCodecInfoIdList(MEDIA_AUDIO),
account.getActiveAccountCodecInfoIdList(MEDIA_VIDEO),
account.getActiveAccountCodecInfoList(MEDIA_AUDIO),
account.getActiveAccountCodecInfoList(MEDIA_VIDEO),
account.getSrtpKeyExchange()
);
localSDP.startNegotiation();
......@@ -924,8 +924,8 @@ sdp_create_offer_cb(pjsip_inv_session *inv, pjmedia_sdp_session **p_offer)
auto& localSDP = call->getSDP();
localSDP.setPublishedIP(address);
const bool created = localSDP.createOffer(
account.getActiveAccountCodecInfoIdList(MEDIA_AUDIO),
account.getActiveAccountCodecInfoIdList(MEDIA_VIDEO),
account.getActiveAccountCodecInfoList(MEDIA_AUDIO),
account.getActiveAccountCodecInfoList(MEDIA_VIDEO),
account.getSrtpKeyExchange()
);
......@@ -1379,7 +1379,5 @@ SIPVoIPLink::findLocalAddressFromSTUN(pjsip_transport* transport,
IpAddr(mapped_addr).toString(true).c_str(), stunServerName->slen,
stunServerName->ptr);
}
#undef RETURN_IF_NULL
} // namespace ring
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