Commit 81b7a757 authored by Alexandre Savard's avatar Alexandre Savard

Merge branch 'master' of...

Merge branch 'master' of git+ssh://git.sflphone.org/var/repos/sflphone/git/sflphone into pjsipupdate
parents 6a0fa7a7 3844589c
[submodule "kde"]
path = kde
url = https://github.com/Elv13/sflphone-kde.git
url = http://anongit.kde.org/sflphone-kde.git
......@@ -46,6 +46,7 @@ const char * const Account::AUDIO_CODECS_KEY = "audioCodecs"; // 0/9/110/1
const char * const Account::VIDEO_CODECS_KEY = "videoCodecs";
const char * const Account::VIDEO_CODEC_ENABLED = "enabled";
const char * const Account::VIDEO_CODEC_NAME = "name";
const char * const Account::VIDEO_CODEC_PARAMETERS ="parameters";
const char * const Account::VIDEO_CODEC_BITRATE = "bitrate";
const char * const Account::RINGTONE_PATH_KEY = "ringtonePath";
const char * const Account::RINGTONE_ENABLED_KEY = "ringtoneEnabled";
......@@ -146,7 +147,7 @@ namespace {
bool isCodecValid(const map<string, string> &codec, const vector<map<string, string> > &defaults)
{
map<string, string>::const_iterator name(codec.find(Account::VIDEO_CODEC_NAME));
const map<string, string>::const_iterator name(codec.find(Account::VIDEO_CODEC_NAME));
if (name == codec.end()) {
ERROR("Field \"name\" missing in codec specification");
return false;
......@@ -154,7 +155,7 @@ namespace {
// check that it's in the list of valid codecs and that it has all the required fields
for (vector<map<string, string> >::const_iterator i = defaults.begin(); i != defaults.end(); ++i) {
map<string, string>::const_iterator defaultName = i->find(Account::VIDEO_CODEC_NAME);
const map<string, string>::const_iterator defaultName = i->find(Account::VIDEO_CODEC_NAME);
if (defaultName->second == name->second) {
return isFieldValid(codec, Account::VIDEO_CODEC_BITRATE, isPositiveInteger)
and isFieldValid(codec, Account::VIDEO_CODEC_ENABLED, isBoolean);
......@@ -199,7 +200,7 @@ void Account::setActiveAudioCodecs(const vector<string> &list)
audioCodecList_.clear();
// list contains the ordered payload of active codecs picked by the user for this account
// we used the CodecOrder vector to save the order.
// we used the codec vector to save the order.
for (vector<string>::const_iterator iter = list.begin(); iter != list.end();
++iter) {
int payload = std::atoi(iter->c_str());
......
......@@ -141,7 +141,7 @@ class Account : public Serializable {
getActiveVideoCodecs() const;
/* Accessor to data structures
* @return CodecOrder& The list that reflects the user's choice
* @return The list that reflects the user's choice
*/
std::vector<int> getActiveAudioCodecs() const {
return audioCodecList_;
......@@ -185,6 +185,7 @@ class Account : public Serializable {
static const char * const VIDEO_CODEC_ENABLED;
static const char * const VIDEO_CODEC_NAME;
static const char * const VIDEO_CODEC_PARAMETERS;
static const char * const VIDEO_CODEC_BITRATE;
private:
NON_COPYABLE(Account);
......
......@@ -38,68 +38,75 @@
*/
// Account identifier
static const char *const CONFIG_ACCOUNT_ID = "Account.id";
static const char *const CONFIG_ACCOUNT_ID = "Account.id";
// Common account parameters
static const char *const CONFIG_ACCOUNT_TYPE = "Account.type";
static const char *const CONFIG_ACCOUNT_ALIAS = "Account.alias";
static const char *const CONFIG_ACCOUNT_MAILBOX = "Account.mailbox";
static const char *const CONFIG_ACCOUNT_ENABLE = "Account.enable";
static const char *const CONFIG_ACCOUNT_REGISTRATION_EXPIRE = "Account.registrationExpire";
static const char *const CONFIG_ACCOUNT_REGISTRATION_STATUS = "Account.registrationStatus";
static const char *const CONFIG_ACCOUNT_TYPE = "Account.type";
static const char *const CONFIG_ACCOUNT_ALIAS = "Account.alias";
static const char *const CONFIG_ACCOUNT_MAILBOX = "Account.mailbox";
static const char *const CONFIG_ACCOUNT_ENABLE = "Account.enable";
static const char *const CONFIG_ACCOUNT_REGISTRATION_EXPIRE = "Account.registrationExpire";
static const char *const CONFIG_ACCOUNT_REGISTRATION_STATUS = "Account.registrationStatus";
static const char *const CONFIG_ACCOUNT_REGISTRATION_STATE_CODE = "Account.registrationCode";
static const char *const CONFIG_ACCOUNT_REGISTRATION_STATE_DESC = "Account.registrationDescription";
static const char *const CONFIG_CREDENTIAL_NUMBER = "Credential.count";
static const char *const CONFIG_ACCOUNT_DTMF_TYPE = "Account.dtmfType";
static const char *const CONFIG_RINGTONE_PATH = "Account.ringtonePath";
static const char *const CONFIG_RINGTONE_ENABLED = "Account.ringtoneEnabled";
static const char *const CONFIG_KEEP_ALIVE_ENABLED = "Account.keepAliveEnabled";
static const char *const CONFIG_CREDENTIAL_NUMBER = "Credential.count";
static const char *const CONFIG_ACCOUNT_DTMF_TYPE = "Account.dtmfType";
static const char *const CONFIG_RINGTONE_PATH = "Account.ringtonePath";
static const char *const CONFIG_RINGTONE_ENABLED = "Account.ringtoneEnabled";
static const char *const CONFIG_KEEP_ALIVE_ENABLED = "Account.keepAliveEnabled";
static const char *const CONFIG_ACCOUNT_HOSTNAME = "Account.hostname";
static const char *const CONFIG_ACCOUNT_USERNAME = "Account.username";
static const char *const CONFIG_ACCOUNT_ROUTESET = "Account.routeset";
static const char *const CONFIG_ACCOUNT_PASSWORD = "Account.password";
static const char *const CONFIG_ACCOUNT_REALM = "Account.realm";
static const char *const CONFIG_ACCOUNT_DEFAULT_REALM = "*";
static const char *const CONFIG_ACCOUNT_USERAGENT = "Account.useragent";
static const char *const CONFIG_LOCAL_INTERFACE = "Account.localInterface";
static const char *const CONFIG_PUBLISHED_SAMEAS_LOCAL = "Account.publishedSameAsLocal";
static const char *const CONFIG_LOCAL_PORT = "Account.localPort";
static const char *const CONFIG_PUBLISHED_PORT = "Account.publishedPort";
static const char *const CONFIG_PUBLISHED_ADDRESS = "Account.publishedAddress";
static const char *const CONFIG_DEFAULT_REGISTRATION_EXPIRE = "60";
static const char *const CONFIG_DISPLAY_NAME = "Account.displayName";
static const char *const CONFIG_DEFAULT_ADDRESS = "0.0.0.0";
static const char *const CONFIG_ACCOUNT_HOSTNAME = "Account.hostname";
static const char *const CONFIG_ACCOUNT_USERNAME = "Account.username";
static const char *const CONFIG_ACCOUNT_ROUTESET = "Account.routeset";
static const char *const CONFIG_ACCOUNT_PASSWORD = "Account.password";
static const char *const CONFIG_ACCOUNT_REALM = "Account.realm";
static const char *const CONFIG_ACCOUNT_DEFAULT_REALM = "*";
static const char *const CONFIG_ACCOUNT_USERAGENT = "Account.useragent";
static const char *const CONFIG_LOCAL_INTERFACE = "Account.localInterface";
static const char *const CONFIG_INTERFACE = "Account.interface";
static const char *const CONFIG_PUBLISHED_SAMEAS_LOCAL = "Account.publishedSameAsLocal";
static const char *const CONFIG_LOCAL_PORT = "Account.localPort";
static const char *const CONFIG_PUBLISHED_PORT = "Account.publishedPort";
static const char *const CONFIG_PUBLISHED_ADDRESS = "Account.publishedAddress";
static const char *const CONFIG_DEFAULT_LOCAL_PORT = "5060";
static const char *const CONFIG_DEFAULT_PUBLISHED_PORT = "5060";
static const char *const CONFIG_DEFAULT_PUBLISHED_SAMEAS_LOCAL = "true";
static const char *const CONFIG_DEFAULT_INTERFACE = "default";
static const char *const CONFIG_DISPLAY_NAME = "Account.displayName";
static const char *const CONFIG_DEFAULT_ADDRESS = "0.0.0.0";
// SIP specific parameters
static const char *const CONFIG_SIP_PROXY = "SIP.proxy";
static const char *const CONFIG_STUN_SERVER = "STUN.server";
static const char *const CONFIG_STUN_ENABLE = "STUN.enable";
static const char *const CONFIG_STUN_SERVER = "STUN.server";
static const char *const CONFIG_STUN_ENABLE = "STUN.enable";
// SRTP specific parameters
static const char *const CONFIG_SRTP_ENABLE = "SRTP.enable";
static const char *const CONFIG_SRTP_KEY_EXCHANGE = "SRTP.keyExchange";
static const char *const CONFIG_SRTP_ENCRYPTION_ALGO = "SRTP.encryptionAlgorithm"; // Provided by ccRTP,0=NULL,1=AESCM,2=AESF8
static const char *const CONFIG_SRTP_RTP_FALLBACK = "SRTP.rtpFallback";
static const char *const CONFIG_ZRTP_HELLO_HASH = "ZRTP.helloHashEnable";
static const char *const CONFIG_ZRTP_DISPLAY_SAS = "ZRTP.displaySAS";
static const char *const CONFIG_ZRTP_NOT_SUPP_WARNING = "ZRTP.notSuppWarning";
static const char *const CONFIG_ZRTP_DISPLAY_SAS_ONCE = "ZRTP.displaySasOnce";
static const char *const CONFIG_SRTP_ENABLE = "SRTP.enable";
static const char *const CONFIG_SRTP_KEY_EXCHANGE = "SRTP.keyExchange";
static const char *const CONFIG_SRTP_ENCRYPTION_ALGO = "SRTP.encryptionAlgorithm"; // Provided by ccRTP,0=NULL,1=AESCM,2=AESF8
static const char *const CONFIG_SRTP_RTP_FALLBACK = "SRTP.rtpFallback";
static const char *const CONFIG_ZRTP_HELLO_HASH = "ZRTP.helloHashEnable";
static const char *const CONFIG_ZRTP_DISPLAY_SAS = "ZRTP.displaySAS";
static const char *const CONFIG_ZRTP_NOT_SUPP_WARNING = "ZRTP.notSuppWarning";
static const char *const CONFIG_ZRTP_DISPLAY_SAS_ONCE = "ZRTP.displaySasOnce";
static const char *const CONFIG_TLS_LISTENER_PORT = "TLS.listenerPort";
static const char *const CONFIG_TLS_ENABLE = "TLS.enable";
static const char *const CONFIG_TLS_CA_LIST_FILE = "TLS.certificateListFile";
static const char *const CONFIG_TLS_CERTIFICATE_FILE = "TLS.certificateFile";
static const char *const CONFIG_TLS_PRIVATE_KEY_FILE = "TLS.privateKeyFile";
static const char *const CONFIG_TLS_PASSWORD = "TLS.password";
static const char *const CONFIG_TLS_METHOD = "TLS.method";
static const char *const CONFIG_TLS_CIPHERS = "TLS.ciphers";
static const char *const CONFIG_TLS_SERVER_NAME = "TLS.serverName";
static const char *const CONFIG_TLS_VERIFY_SERVER = "TLS.verifyServer";
static const char *const CONFIG_TLS_VERIFY_CLIENT = "TLS.verifyClient";
static const char *const CONFIG_TLS_REQUIRE_CLIENT_CERTIFICATE = "TLS.requireClientCertificate";
static const char *const CONFIG_TLS_NEGOTIATION_TIMEOUT_SEC = "TLS.negotiationTimeoutSec";
static const char *const CONFIG_TLS_NEGOTIATION_TIMEOUT_MSEC = "TLS.negotiationTimemoutMsec";
static const char *const CONFIG_TLS_LISTENER_PORT = "TLS.listenerPort";
static const char *const CONFIG_TLS_ENABLE = "TLS.enable";
static const char *const CONFIG_TLS_CA_LIST_FILE = "TLS.certificateListFile";
static const char *const CONFIG_TLS_CERTIFICATE_FILE = "TLS.certificateFile";
static const char *const CONFIG_TLS_PRIVATE_KEY_FILE = "TLS.privateKeyFile";
static const char *const CONFIG_TLS_PASSWORD = "TLS.password";
static const char *const CONFIG_TLS_METHOD = "TLS.method";
static const char *const CONFIG_TLS_CIPHERS = "TLS.ciphers";
static const char *const CONFIG_TLS_SERVER_NAME = "TLS.serverName";
static const char *const CONFIG_TLS_VERIFY_SERVER = "TLS.verifyServer";
static const char *const CONFIG_TLS_VERIFY_CLIENT = "TLS.verifyClient";
static const char *const CONFIG_TLS_REQUIRE_CLIENT_CERTIFICATE = "TLS.requireClientCertificate";
static const char *const CONFIG_TLS_NEGOTIATION_TIMEOUT_SEC = "TLS.negotiationTimeoutSec";
static const char *const CONFIG_TLS_NEGOTIATION_TIMEOUT_MSEC = "TLS.negotiationTimemoutMsec";
#endif
......@@ -40,8 +40,6 @@
namespace sfl {
static const SFLDataFormat INIT_FADE_IN_FACTOR = 32000;
#ifdef RECTODISK
std::ofstream rtpResampled ("testRtpOutputResampled.raw", std::ifstream::binary);
std::ofstream rtpNotResampled("testRtpOutput.raw", std::ifstream::binary);
......@@ -69,7 +67,7 @@ AudioRtpRecord::AudioRtpRecord() :
, codecFrameSize_(0)
, converterSamplingRate_(0)
, dtmfQueue_()
, fadeFactor_(INIT_FADE_IN_FACTOR)
, fadeFactor_(1.0 / 32000.0)
#if HAVE_SPEEXDSP
, noiseSuppressEncode_(0)
, noiseSuppressDecode_(0)
......@@ -259,15 +257,15 @@ void AudioRtpRecordHandler::processDataDecode(unsigned char *spkrData, size_t si
void AudioRtpRecord::fadeInDecodedData(size_t size)
{
// if factor reaches 0, this function should have no effect
if (fadeFactor_ <= 0 or size > decData_.size())
// if factor reaches 1, this function should have no effect
if (fadeFactor_ >= 1.0 or size > decData_.size())
return;
std::transform(decData_.begin(), decData_.begin() + size, decData_.begin(),
std::bind1st(std::divides<double>(), fadeFactor_));
std::bind1st(std::multiplies<double>(), fadeFactor_));
// Factor used to increase volume in fade in
const SFLDataFormat FADEIN_STEP_SIZE = 4;
fadeFactor_ /= FADEIN_STEP_SIZE;
const double FADEIN_STEP_SIZE = 4.0;
fadeFactor_ *= FADEIN_STEP_SIZE;
}
}
......@@ -89,7 +89,7 @@ class AudioRtpRecord {
int codecFrameSize_;
int converterSamplingRate_;
std::list<DTMFEvent> dtmfQueue_;
SFLDataFormat fadeFactor_;
double fadeFactor_;
#if HAVE_SPEEXDSP
NoiseSuppress *noiseSuppressEncode_;
......
......@@ -128,7 +128,7 @@ void AudioCodecFactory::saveActiveCodecs(const std::vector<std::string>& list)
{
defaultCodecList_.clear();
// list contains the ordered payload of active codecs picked by the user
// we used the CodecOrder vector to save the order.
// we used the codec vector to save the order.
for (std::vector<std::string>::const_iterator iter = list.begin(); iter != list.end(); ++iter) {
int payload = std::atoi(iter->c_str());
......
......@@ -6,6 +6,12 @@
Used to handle the configuration stuff: accounts settings, account registration, user preferences, ...
</tp:docstring>
<method name="getAccountTemplate" tp:name-for-bindings="getAccountTemplate">
<annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="MapStringString"/>
<arg type="a{ss}" name="details" direction="out" tp:type="String_String_Map">
</arg>
</method>
<method name="getAccountDetails" tp:name-for-bindings="getAccountDetails">
<tp:docstring>
Get all parameters of the specified account.
......@@ -187,19 +193,15 @@
<method name="registerAllAccounts" tp:name-for-bindings="registerAllAccounts">
<tp:docstring>
Send account registration (REGISTER) for all currently registered account.
Send account registration (REGISTER) for all accounts, even if they are not enabled.
</tp:docstring>
Register each account for which enable=true
</method>
<method name="sendRegister" tp:name-for-bindings="sendRegister">
<tp:docstring>
Send account registration (REGISTER) to the registrar.
Register the account if enable=true, unregister if enable=false.
</tp:docstring>
Register the account if enable=true, unregister if enable=false.
@param[in] input accountID
-->
<arg type="s" name="accountID" direction="in">
<tp:docstring>
The account ID
......
......@@ -150,6 +150,18 @@ void ConfigurationManager::registerAllAccounts()
Manager::instance().registerAllAccounts();
}
///This function is used as a base for new accounts for clients that support it
std::map<std::string, std::string> ConfigurationManager::getAccountTemplate()
{
std::map<std::string, std::string> accTemplate;
accTemplate[ CONFIG_LOCAL_PORT ] = CONFIG_DEFAULT_LOCAL_PORT;
accTemplate[ CONFIG_PUBLISHED_PORT ] = CONFIG_DEFAULT_PUBLISHED_PORT;
accTemplate[ CONFIG_PUBLISHED_SAMEAS_LOCAL ] = CONFIG_DEFAULT_PUBLISHED_SAMEAS_LOCAL;
accTemplate[ CONFIG_INTERFACE ] = CONFIG_DEFAULT_INTERFACE;
accTemplate[ CONFIG_ACCOUNT_REGISTRATION_EXPIRE ] = CONFIG_DEFAULT_REGISTRATION_EXPIRE;
return accTemplate;
}
std::string ConfigurationManager::addAccount(const std::map<std::string, std::string>& details)
{
return Manager::instance().addAccount(details);
......
......@@ -61,6 +61,7 @@ class ConfigurationManager
ConfigurationManager(DBus::Connection& connection);
std::map< std::string, std::string > getAccountDetails(const std::string& accountID);
void setAccountDetails(const std::string& accountID, const std::map< std::string, std::string >& details);
std::map<std::string, std::string> getAccountTemplate();
std::string addAccount(const std::map< std::string, std::string >& details);
void removeAccount(const std::string& accoundID);
void deleteAllCredential(const std::string& accountID);
......
......@@ -107,7 +107,4 @@ enum {
PAYLOAD_CODEC_SPEEX_32000 = 112
};
/** The struct to reflect the order the user wants to use the codecs */
typedef std::vector<int> CodecOrder;
#endif // __GLOBAL_H__
......@@ -2669,7 +2669,8 @@ ManagerImpl::getAccount(const std::string& accountID)
return accountMap_[SIPAccount::IP2IP_PROFILE];
}
std::string ManagerImpl::getAccountIdFromNameAndServer(const std::string& userName, const std::string& server) const
std::string
ManagerImpl::getAccountIdFromNameAndServer(const std::string& userName, const std::string& server) const
{
DEBUG("username = %s, server = %s", userName.c_str(), server.c_str());
// Try to find the account id from username and server name by full match
......@@ -2703,6 +2704,16 @@ std::string ManagerImpl::getAccountIdFromNameAndServer(const std::string& userNa
}
}
// We failed! Then only match the hostname against our proxy
for (AccountMap::const_iterator iter = accountMap_.begin(); iter != accountMap_.end(); ++iter) {
SIPAccount *account = dynamic_cast<SIPAccount *>(iter->second);
if (account and account->isEnabled() and account->proxyMatch(server)) {
DEBUG("Matching account id in request with proxy %s", server.c_str());
return iter->first;
}
}
DEBUG("Username %s or server %s doesn't match any account, using IP2IP", userName.c_str(), server.c_str());
return "";
}
......
......@@ -40,6 +40,10 @@
#include <algorithm>
#ifdef SFL_VIDEO
#include "video/libav_utils.h"
#endif
using std::string;
using std::map;
using std::vector;
......@@ -163,7 +167,8 @@ sfl::AudioCodec* Sdp::getSessionAudioMedia() const
}
pjmedia_sdp_media *Sdp::setMediaDescriptorLine(bool audio)
pjmedia_sdp_media *
Sdp::setMediaDescriptorLine(bool audio)
{
pjmedia_sdp_media *med = PJ_POOL_ZALLOC_T(memPool_, pjmedia_sdp_media);
......@@ -216,13 +221,18 @@ pjmedia_sdp_media *Sdp::setMediaDescriptorLine(bool audio)
pjmedia_sdp_rtpmap_to_attr(memPool_, &rtpmap, &attr);
med->attr[med->attr_count++] = attr;
#ifdef SFL_VIDEO
if (enc_name == "H264") {
std::ostringstream os;
// FIXME: this should not be hardcoded, it will determine what profile and level
// our peer will send us
os << "fmtp:" << dynamic_payload << " profile-level-id=428014";
std::string profileLevelID(video_codec_list_[i]["parameters"]);
if (profileLevelID.empty())
profileLevelID = libav_utils::MAX_H264_PROFILE_LEVEL_ID;
os << "fmtp:" << dynamic_payload << " " << profileLevelID;
med->attr[med->attr_count++] = pjmedia_sdp_attr_create(memPool_, os.str().c_str(), NULL);
}
#endif
if (not audio)
dynamic_payload++;
}
......@@ -424,12 +434,16 @@ string Sdp::getLineFromSession(const pjmedia_sdp_session *sess, const string &ke
return "";
}
string Sdp::getActiveIncomingVideoDescription() const
// FIXME:
// Here we filter out parts of the SDP that libavformat doesn't need to
// know about...we should probably give the video decoder thread the original
// SDP and deal with the streams properly at that level
string Sdp::getIncomingVideoDescription() const
{
stringstream ss;
ss << "v=0" << std::endl;
ss << "o=- 0 0 IN IP4 " << localIpAddr_ << std::endl;
ss << "s=sflphone" << std::endl;
ss << "s=" << PACKAGE_NAME << std::endl;
ss << "c=IN IP4 " << remoteIpAddr_ << std::endl;
ss << "t=0 0" << std::endl;
......@@ -447,6 +461,11 @@ string Sdp::getActiveIncomingVideoDescription() const
std::string vCodecLine(getLineFromSession(activeLocalSession_, s.str()));
ss << vCodecLine << std::endl;
std::string profileLevelID;
getProfileLevelID(activeLocalSession_, profileLevelID, payload_num);
if (not profileLevelID.empty())
ss << "a=fmtp:" << payload_num << " " << profileLevelID << std::endl;
unsigned videoIdx;
for (videoIdx = 0; videoIdx < activeLocalSession_->media_count and pj_stricmp2(&activeLocalSession_->media[videoIdx]->desc.media, "video") != 0; ++videoIdx)
;
......@@ -471,10 +490,12 @@ string Sdp::getActiveIncomingVideoDescription() const
return ss.str();
}
std::string Sdp::getActiveOutgoingVideoCodec() const
std::string Sdp::getOutgoingVideoCodec() const
{
string str("a=rtpmap:");
str += getActiveOutgoingVideoPayload();
std::stringstream os;
os << getOutgoingVideoPayload();
str += os.str();
string vCodecLine(getLineFromSession(activeRemoteSession_, str));
char codec_buf[32];
codec_buf[0] = '\0';
......@@ -482,28 +503,55 @@ std::string Sdp::getActiveOutgoingVideoCodec() const
return string(codec_buf);
}
std::string Sdp::getActiveOutgoingVideoBitrate(const std::string &codec) const
{
for (vector<map<string, string> >::const_iterator i = video_codec_list_.begin(); i != video_codec_list_.end(); ++i) {
map<string, string>::const_iterator name = i->find("name");
if (name != i->end() and (codec == name->second)) {
map<string, string>::const_iterator bitrate = i->find("bitrate");
if (bitrate != i->end())
return bitrate->second;
namespace {
vector<map<string, string> >::const_iterator
findCodecInList(const vector<map<string, string> > &codecs, const string &codec)
{
for (vector<map<string, string> >::const_iterator i = codecs.begin(); i != codecs.end(); ++i) {
map<string, string>::const_iterator name = i->find("name");
if (name != i->end() and (codec == name->second))
return i;
}
return codecs.end();
}
}
std::string
Sdp::getOutgoingVideoField(const std::string &codec, const char *key) const
{
const vector<map<string, string> >::const_iterator i = findCodecInList(video_codec_list_, codec);
if (i != video_codec_list_.end()) {
map<string, string>::const_iterator field = i->find(key);
if (field != i->end())
return field->second;
}
return "0";
return "";
}
std::string Sdp::getActiveOutgoingVideoPayload() const
int
Sdp::getOutgoingVideoPayload() const
{
string videoLine(getLineFromSession(activeRemoteSession_, "m=video"));
int payload_num;
if (sscanf(videoLine.c_str(), "m=video %*d %*s %d", &payload_num) != 1)
payload_num = 0;
return payload_num;
}
void
Sdp::getProfileLevelID(const pjmedia_sdp_session *session,
std::string &profile, int payload) const
{
std::ostringstream os;
os << payload_num;
return os.str();
os << "a=fmtp:" << payload;
string fmtpLine(getLineFromSession(session, os.str()));
const std::string needle("profile-level-id=");
const size_t DIGITS_IN_PROFILE_LEVEL_ID = 6;
const size_t needleLength = needle.size() + DIGITS_IN_PROFILE_LEVEL_ID;
const size_t pos = fmtpLine.find(needle);
if (pos != std::string::npos and fmtpLine.size() >= (pos + needleLength))
profile = fmtpLine.substr(pos, needleLength);
DEBUG("Using %s", profile.c_str());
}
void Sdp::addSdesAttribute(const vector<std::string>& crypto)
......@@ -539,7 +587,7 @@ namespace {
ERROR("Session is NULL when looking for \"%s\" attribute", type);
return -1;
}
int i = 0;
size_t i = 0;
while (i < session->media_count and pj_stricmp2(&session->media[i]->desc.media, type) != 0)
++i;
......@@ -616,3 +664,28 @@ void Sdp::getRemoteSdpCryptoFromOffer(const pjmedia_sdp_session* remote_sdp, Cry
}
}
}
bool Sdp::getOutgoingVideoSettings(map<string, string> &args) const
{
#ifdef SFL_VIDEO
string codec(getOutgoingVideoCodec());
if (not codec.empty()) {
const string encoder(libav_utils::encodersMap()[codec]);
if (encoder.empty()) {
DEBUG("Couldn't find encoder for \"%s\"\n", codec.c_str());
return false;
} else {
args["codec"] = encoder;
args["bitrate"] = getOutgoingVideoField(codec, "bitrate");
const int payload = getOutgoingVideoPayload();
std::ostringstream os;
os << payload;
args["payload_type"] = os.str();
// override with profile-level-id from remote, if present
getProfileLevelID(activeRemoteSession_, args["parameters"], payload);
}
return true;
}
#endif
return false;
}
......@@ -113,10 +113,7 @@ class Sdp {
* Returns a string version of the negotiated SDP fields which pertain
* to video.
*/
std::string getActiveIncomingVideoDescription() const;
std::string getActiveOutgoingVideoCodec() const;
std::string getActiveOutgoingVideoBitrate(const std::string &codec) const;
std::string getActiveOutgoingVideoPayload() const;
std::string getIncomingVideoDescription() const;
/*
* On building an invite outside a dialog, build the local offer and create the
......@@ -242,12 +239,19 @@ class Sdp {
std::string getAudioCodecName() const;
std::string getSessionVideoCodec() const;
sfl::AudioCodec* getSessionAudioMedia() const;
// Sets @param settings with appropriate values and returns true if
// we are sending video, false otherwise
bool getOutgoingVideoSettings(std::map<std::string, std::string> &settings) const;
private:
NON_COPYABLE(Sdp);
friend class SDPTest;
std::string getLineFromSession(const pjmedia_sdp_session *sess, const std::string &keyword) const;
std::string getOutgoingVideoCodec() const;
std::string getOutgoingVideoField(const std::string &codec, const char *key) const;
int getOutgoingVideoPayload() const;
void getProfileLevelID(const pjmedia_sdp_session *session, std::string &dest, int payload) const;
/**
* The pool to allocate memory, ownership to SipCall
......
......@@ -42,6 +42,13 @@
#include <pj/list.h>
#include "sip_utils.h"
// for resolveDns
#include <list>
#include <netdb.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
std::string
sip_utils::fetchHeaderValue(pjsip_msg *msg, const std::string &field)
{
......@@ -124,3 +131,41 @@ sip_utils::stripSipUriPrefix(std::string& sipUri)
if (found != std::string::npos)
sipUri.erase(found);
}