- more changes to allow CI runs on this project
This commit is contained in:
parent
228e2d7829
commit
7d4933b066
|
|
@ -1,5 +1,7 @@
|
||||||
project(rtphone)
|
project(rtphone)
|
||||||
|
|
||||||
|
cmake_minimum_required(VERSION 3.0)
|
||||||
|
|
||||||
macro(configure_msvc_runtime)
|
macro(configure_msvc_runtime)
|
||||||
if(MSVC)
|
if(MSVC)
|
||||||
# Default to statically-linked runtime.
|
# Default to statically-linked runtime.
|
||||||
|
|
@ -59,11 +61,25 @@ set (USE_AMR_CODEC OFF CACHE BOOL "Use AMR codec. Requires libraries.")
|
||||||
set (USE_EVS_CODEC OFF CACHE BOOL "Use EVS codec.")
|
set (USE_EVS_CODEC OFF CACHE BOOL "Use EVS codec.")
|
||||||
set (OPENSSL_SSL ssl CACHE STRING "Pointer to ssl library")
|
set (OPENSSL_SSL ssl CACHE STRING "Pointer to ssl library")
|
||||||
set (OPENSSL_CRYPTO crypto CACHE STRING "Pointer to crypto library")
|
set (OPENSSL_CRYPTO crypto CACHE STRING "Pointer to crypto library")
|
||||||
|
set (OPENSSL_INCLUDE "/usr/local/include/openssl" CACHE STRING "Pointer to OpenSSL include files")
|
||||||
|
|
||||||
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
||||||
|
|
||||||
message ("Using ssl library at ${OPENSSL_SSL}")
|
message ("Using ssl library at ${OPENSSL_SSL}")
|
||||||
message ("Using crypto library at ${OPENSSL_CRYPTO}")
|
message ("Using crypto library at ${OPENSSL_CRYPTO}")
|
||||||
|
message ("Using OpenSSL include files from ${OPENSSL_INCLUDE}")
|
||||||
|
|
||||||
|
if (CMAKE_SYSTEM MATCHES "Windows*")
|
||||||
|
add_definitions(-DTARGET_WIN)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if (CMAKE_SYSTEM MATCHES "Linux*")
|
||||||
|
add_definitions(-DTARGET_LINUX)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if (CMAKE_SYSTEM MATCHES "Darwin*")
|
||||||
|
add_definitions(-DTARGET_OSX)
|
||||||
|
endif()
|
||||||
|
|
||||||
set (RTPHONE_SOURCES
|
set (RTPHONE_SOURCES
|
||||||
${rtphone_engine}/media/MT_Statistics.cpp
|
${rtphone_engine}/media/MT_Statistics.cpp
|
||||||
|
|
@ -94,10 +110,39 @@ set (RTPHONE_SOURCES
|
||||||
${rtphone_engine}/endpoint/EP_Session.cpp
|
${rtphone_engine}/endpoint/EP_Session.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
add_library(rtphone STATIC ${RTPHONE_SOURCES})
|
set (RTPHONE_HEADERS
|
||||||
|
${rtphone_engine}/media/MT_Statistics.h
|
||||||
|
${rtphone_engine}/media/MT_WebRtc.h
|
||||||
|
${rtphone_engine}/media/MT_Stream.h
|
||||||
|
${rtphone_engine}/media/MT_SrtpHelper.h
|
||||||
|
${rtphone_engine}/media/MT_SingleAudioStream.h
|
||||||
|
${rtphone_engine}/media/MT_NativeRtpSender.h
|
||||||
|
${rtphone_engine}/media/MT_Dtmf.h
|
||||||
|
${rtphone_engine}/media/MT_CodecList.h
|
||||||
|
${rtphone_engine}/media/MT_Codec.h
|
||||||
|
${rtphone_engine}/media/MT_Box.h
|
||||||
|
${rtphone_engine}/media/MT_AudioStream.h
|
||||||
|
${rtphone_engine}/media/MT_AudioReceiver.h
|
||||||
|
${rtphone_engine}/media/MT_AudioCodec.h
|
||||||
|
${rtphone_engine}/media/MT_SevanaMos.h
|
||||||
|
${rtphone_engine}/media/MT_AmrCodec.h
|
||||||
|
${rtphone_engine}/media/MT_EvsCodec.h
|
||||||
|
${rtphone_engine}/media/MT_CngHelper.h
|
||||||
|
${rtphone_engine}/agent/Agent_Impl.h
|
||||||
|
${rtphone_engine}/agent/Agent_AudioManager.h
|
||||||
|
${rtphone_engine}/endpoint/EP_Account.h
|
||||||
|
${rtphone_engine}/endpoint/EP_AudioProvider.h
|
||||||
|
${rtphone_engine}/endpoint/EP_DataProvider.h
|
||||||
|
${rtphone_engine}/endpoint/EP_Engine.h
|
||||||
|
${rtphone_engine}/endpoint/EP_NetworkQueue.h
|
||||||
|
${rtphone_engine}/endpoint/EP_Observer.h
|
||||||
|
${rtphone_engine}/endpoint/EP_Session.h
|
||||||
|
)
|
||||||
|
add_library(rtphone STATIC ${RTPHONE_SOURCES} ${RTPHONE_HEADERS})
|
||||||
|
|
||||||
add_subdirectory(${rtphone_engine}/helper)
|
add_subdirectory(${rtphone_engine}/helper)
|
||||||
add_subdirectory(${rtphone_engine}/audio)
|
add_subdirectory(${rtphone_engine}/audio)
|
||||||
|
add_subdirectory(${rtphone_engine}/media)
|
||||||
add_subdirectory(${rtphone_libs}/resiprocate)
|
add_subdirectory(${rtphone_libs}/resiprocate)
|
||||||
add_subdirectory(${rtphone_libs}/ice)
|
add_subdirectory(${rtphone_libs}/ice)
|
||||||
add_subdirectory(${rtphone_libs}/jrtplib/src)
|
add_subdirectory(${rtphone_libs}/jrtplib/src)
|
||||||
|
|
@ -116,9 +161,9 @@ set(LIBS ice_stack jrtplib g729_codec gsm_codec
|
||||||
|
|
||||||
if (CMAKE_SYSTEM MATCHES "Win*")
|
if (CMAKE_SYSTEM MATCHES "Win*")
|
||||||
set (LIBS ${LIBS} opus )
|
set (LIBS ${LIBS} opus )
|
||||||
else (CMAKE_SYSTEM MATCHES "Win*")
|
else ()
|
||||||
set (LIBS ${LIBS} dl opus uuid)
|
set (LIBS ${LIBS} dl opus uuid)
|
||||||
endif (CMAKE_SYSTEM MATCHES "Win*")
|
endif ()
|
||||||
|
|
||||||
if (USE_AMR_CODEC)
|
if (USE_AMR_CODEC)
|
||||||
set(LIBS ${LIBS} opencore-amrnb opencore-amrwb)
|
set(LIBS ${LIBS} opencore-amrnb opencore-amrwb)
|
||||||
|
|
@ -134,6 +179,11 @@ target_link_libraries(rtphone
|
||||||
target_include_directories(rtphone
|
target_include_directories(rtphone
|
||||||
PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
|
PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
|
||||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/engine>
|
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/engine>
|
||||||
PRIVATE ../../libs/speex/include ../../libs ../)
|
|
||||||
|
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/libs/
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/libs/speex/include
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/libs/opus/include/
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/libs/json
|
||||||
|
)
|
||||||
|
|
||||||
configure_msvc_runtime()
|
configure_msvc_runtime()
|
||||||
|
|
|
||||||
|
|
@ -17,16 +17,16 @@
|
||||||
#define LOG_SUBSYSTEM "AudioProvider"
|
#define LOG_SUBSYSTEM "AudioProvider"
|
||||||
|
|
||||||
AudioProvider::AudioProvider(UserAgent& agent, MT::Terminal& terminal)
|
AudioProvider::AudioProvider(UserAgent& agent, MT::Terminal& terminal)
|
||||||
:mUserAgent(agent), mTerminal(terminal), mState(0),
|
:mUserAgent(agent), mTerminal(terminal), mState(0),
|
||||||
mRemoteTelephoneCodec(0), mRemoteNoSdp(false)
|
mRemoteTelephoneCodec(0), mRemoteNoSdp(false)
|
||||||
{
|
{
|
||||||
mActive = mfActive;
|
mActive = mfActive;
|
||||||
mRemoteState = msSendRecv;
|
mRemoteState = msSendRecv;
|
||||||
mActiveStream = mTerminal.createStream(MT::Stream::Audio, mUserAgent.config());
|
mActiveStream = mTerminal.createStream(MT::Stream::Audio, mUserAgent.config());
|
||||||
if (mUserAgent.config().exists(CONFIG_CODEC_PRIORITY))
|
if (mUserAgent.config().exists(CONFIG_CODEC_PRIORITY))
|
||||||
mCodecPriority.setupFrom(mUserAgent.config()[CONFIG_CODEC_PRIORITY].asVMap());
|
mCodecPriority.setupFrom(mUserAgent.config()[CONFIG_CODEC_PRIORITY].asVMap());
|
||||||
mSrtpSuite = SRTP_NONE;
|
mSrtpSuite = SRTP_NONE;
|
||||||
setState((int)StreamState::SipRecv | (int)StreamState::SipSend | (int)StreamState::Receiving | (int)StreamState::Sending);
|
setState((int)StreamState::SipRecv | (int)StreamState::SipSend | (int)StreamState::Receiving | (int)StreamState::Sending);
|
||||||
}
|
}
|
||||||
|
|
||||||
AudioProvider::~AudioProvider()
|
AudioProvider::~AudioProvider()
|
||||||
|
|
@ -35,346 +35,346 @@ AudioProvider::~AudioProvider()
|
||||||
|
|
||||||
std::string AudioProvider::streamName()
|
std::string AudioProvider::streamName()
|
||||||
{
|
{
|
||||||
return "audio";
|
return "audio";
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string AudioProvider::streamProfile()
|
std::string AudioProvider::streamProfile()
|
||||||
{
|
{
|
||||||
if (mState & (int)StreamState::Srtp)
|
if (mState & (int)StreamState::Srtp)
|
||||||
return "RTP/SAVP";
|
return "RTP/SAVP";
|
||||||
else
|
else
|
||||||
return "RTP/AVP";
|
return "RTP/AVP";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sets destination IP address
|
// Sets destination IP address
|
||||||
void AudioProvider::setDestinationAddress(const RtpPair<InternetAddress>& addr)
|
void AudioProvider::setDestinationAddress(const RtpPair<InternetAddress>& addr)
|
||||||
{
|
{
|
||||||
if (!mActiveStream)
|
if (!mActiveStream)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
mActiveStream->setDestination(addr);
|
mActiveStream->setDestination(addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioProvider::configureMediaObserver(MT::Stream::MediaObserver *observer, void* userTag)
|
void AudioProvider::configureMediaObserver(MT::Stream::MediaObserver *observer, void* userTag)
|
||||||
{
|
{
|
||||||
mMediaObserver = observer;
|
mMediaObserver = observer;
|
||||||
mMediaObserverTag = userTag;
|
mMediaObserverTag = userTag;
|
||||||
if (mActiveStream)
|
if (mActiveStream)
|
||||||
mActiveStream->configureMediaObserver(observer, userTag);
|
mActiveStream->configureMediaObserver(observer, userTag);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Processes incoming data
|
// Processes incoming data
|
||||||
void AudioProvider::processData(PDatagramSocket s, const void* dataBuffer, int dataSize, InternetAddress& source)
|
void AudioProvider::processData(PDatagramSocket s, const void* dataBuffer, int dataSize, InternetAddress& source)
|
||||||
{
|
{
|
||||||
if (!mActiveStream)
|
if (!mActiveStream)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (RtpHelper::isRtpOrRtcp(dataBuffer, dataSize))
|
if (RtpHelper::isRtpOrRtcp(dataBuffer, dataSize))
|
||||||
{
|
{
|
||||||
ICELogMedia(<<"Adding new data to stream processing");
|
ICELogMedia(<<"Adding new data to stream processing");
|
||||||
mActiveStream->dataArrived(s, dataBuffer, dataSize, source);
|
mActiveStream->dataArrived(s, dataBuffer, dataSize, source);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// This method is called by user agent to send ICE packet from mediasocket
|
// This method is called by user agent to send ICE packet from mediasocket
|
||||||
void AudioProvider::sendData(PDatagramSocket s, InternetAddress& destination, const void* buffer, unsigned int size)
|
void AudioProvider::sendData(PDatagramSocket s, InternetAddress& destination, const void* buffer, unsigned int size)
|
||||||
{
|
{
|
||||||
s->sendDatagram(destination, buffer, size);
|
s->sendDatagram(destination, buffer, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create SDP offer
|
// Create SDP offer
|
||||||
void AudioProvider::updateSdpOffer(resip::SdpContents::Session::Medium& sdp, SdpDirection direction)
|
void AudioProvider::updateSdpOffer(resip::SdpContents::Session::Medium& sdp, SdpDirection direction)
|
||||||
{
|
{
|
||||||
if (mRemoteNoSdp)
|
if (mRemoteNoSdp)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (mState & (int)StreamState::Srtp)
|
if (mState & (int)StreamState::Srtp)
|
||||||
{
|
|
||||||
// Check if SRTP suite is found already or not
|
|
||||||
if (mSrtpSuite == SRTP_NONE)
|
|
||||||
{
|
{
|
||||||
for (int suite = SRTP_AES_128_AUTH_80; suite <= SRTP_LAST; suite++)
|
// Check if SRTP suite is found already or not
|
||||||
sdp.addAttribute("crypto", resip::Data(createCryptoAttribute((SrtpSuite)suite)));
|
if (mSrtpSuite == SRTP_NONE)
|
||||||
|
{
|
||||||
|
for (int suite = SRTP_AES_128_AUTH_80; suite <= SRTP_LAST; suite++)
|
||||||
|
sdp.addAttribute("crypto", resip::Data(createCryptoAttribute((SrtpSuite)suite)));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
sdp.addAttribute("crypto", resip::Data(createCryptoAttribute(mSrtpSuite)));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use CodecListPriority mCodecPriority adapter to work with codec priorities
|
||||||
|
if (mAvailableCodecs.empty())
|
||||||
|
{
|
||||||
|
for (int i=0; i<mCodecPriority.count(mTerminal.codeclist()); i++)
|
||||||
|
mCodecPriority.codecAt(mTerminal.codeclist(), i).updateSdp(sdp.codecs(), direction);
|
||||||
|
sdp.addCodec(resip::SdpContents::Session::Codec::TelephoneEvent);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
sdp.addAttribute("crypto", resip::Data(createCryptoAttribute(mSrtpSuite)));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Use CodecListPriority mCodecPriority adapter to work with codec priorities
|
|
||||||
if (mAvailableCodecs.empty())
|
|
||||||
{
|
|
||||||
for (int i=0; i<mCodecPriority.count(mTerminal.codeclist()); i++)
|
|
||||||
mCodecPriority.codecAt(mTerminal.codeclist(), i).updateSdp(sdp.codecs(), direction);
|
|
||||||
sdp.addCodec(resip::SdpContents::Session::Codec::TelephoneEvent);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
mAvailableCodecs.front().mFactory->updateSdp(sdp.codecs(), direction);
|
|
||||||
if (mRemoteTelephoneCodec)
|
|
||||||
sdp.addCodec(resip::SdpContents::Session::Codec::TelephoneEvent);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Publish stream state
|
|
||||||
const char* attr = nullptr;
|
|
||||||
switch (mActive)
|
|
||||||
{
|
|
||||||
case mfActive:
|
|
||||||
switch(mRemoteState)
|
|
||||||
{
|
{
|
||||||
case msSendonly: attr = "recvonly"; break;
|
mAvailableCodecs.front().mFactory->updateSdp(sdp.codecs(), direction);
|
||||||
case msInactive: attr = "recvonly"; break;
|
if (mRemoteTelephoneCodec)
|
||||||
|
sdp.addCodec(resip::SdpContents::Session::Codec::TelephoneEvent);
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
|
|
||||||
case mfPaused:
|
// Publish stream state
|
||||||
switch (mRemoteState)
|
const char* attr = nullptr;
|
||||||
|
switch (mActive)
|
||||||
{
|
{
|
||||||
case msRecvonly: attr = "sendonly"; break;
|
case mfActive:
|
||||||
case msSendonly: attr = "inactive"; break;
|
switch(mRemoteState)
|
||||||
case msInactive: attr = "inactive"; break;
|
{
|
||||||
case msSendRecv: attr = "sendonly"; break;
|
case msSendonly: attr = "recvonly"; break;
|
||||||
|
case msInactive: attr = "recvonly"; break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case mfPaused:
|
||||||
|
switch (mRemoteState)
|
||||||
|
{
|
||||||
|
case msRecvonly: attr = "sendonly"; break;
|
||||||
|
case msSendonly: attr = "inactive"; break;
|
||||||
|
case msInactive: attr = "inactive"; break;
|
||||||
|
case msSendRecv: attr = "sendonly"; break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
if (attr)
|
||||||
}
|
sdp.addAttribute(attr);
|
||||||
if (attr)
|
|
||||||
sdp.addAttribute(attr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioProvider::sessionDeleted()
|
void AudioProvider::sessionDeleted()
|
||||||
{
|
{
|
||||||
sessionTerminated();
|
sessionTerminated();
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioProvider::sessionTerminated()
|
void AudioProvider::sessionTerminated()
|
||||||
{
|
{
|
||||||
ICELogDebug(<< "sessionTerminated() for audio provider");
|
ICELogDebug(<< "sessionTerminated() for audio provider");
|
||||||
setState(state() & ~((int)StreamState::Sending | (int)StreamState::Receiving));
|
setState(state() & ~((int)StreamState::Sending | (int)StreamState::Receiving));
|
||||||
|
|
||||||
if (mActiveStream)
|
if (mActiveStream)
|
||||||
{
|
{
|
||||||
ICELogDebug(<< "Copy statistics from existing stream before freeing.");
|
ICELogDebug(<< "Copy statistics from existing stream before freeing.");
|
||||||
|
|
||||||
// Copy statistics - maybe it will be requested later
|
// Copy statistics - maybe it will be requested later
|
||||||
mBackupStats = mActiveStream->statistics();
|
mBackupStats = mActiveStream->statistics();
|
||||||
|
|
||||||
ICELogDebug(<< "Remove stream from terminal");
|
ICELogDebug(<< "Remove stream from terminal");
|
||||||
mTerminal.freeStream(mActiveStream);
|
mTerminal.freeStream(mActiveStream);
|
||||||
|
|
||||||
// Retrieve final statistics
|
// Retrieve final statistics
|
||||||
MT::AudioStream* audio_stream = dynamic_cast<MT::AudioStream*>(mActiveStream.get());
|
MT::AudioStream* audio_stream = dynamic_cast<MT::AudioStream*>(mActiveStream.get());
|
||||||
if (audio_stream)
|
if (audio_stream)
|
||||||
audio_stream->setFinalStatisticsOutput(&mBackupStats);
|
audio_stream->setFinalStatisticsOutput(&mBackupStats);
|
||||||
|
|
||||||
ICELogDebug(<< "Reset reference to stream.");
|
ICELogDebug(<< "Reset reference to stream.");
|
||||||
mActiveStream.reset();
|
mActiveStream.reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioProvider::sessionEstablished(int conntype)
|
void AudioProvider::sessionEstablished(int conntype)
|
||||||
{
|
{
|
||||||
// Start media streams
|
// Start media streams
|
||||||
setState(state() | (int)StreamState::Receiving | (int)StreamState::Sending);
|
setState(state() | (int)StreamState::Receiving | (int)StreamState::Sending);
|
||||||
|
|
||||||
// Available codec list can be empty in case of no-sdp offers.
|
// Available codec list can be empty in case of no-sdp offers.
|
||||||
if (conntype == EV_SIP && !mAvailableCodecs.empty() && mActiveStream)
|
if (conntype == EV_SIP && !mAvailableCodecs.empty() && mActiveStream)
|
||||||
{
|
{
|
||||||
RemoteCodec& rc = mAvailableCodecs.front();
|
RemoteCodec& rc = mAvailableCodecs.front();
|
||||||
mActiveStream->setTransmittingCodec(*rc.mFactory, rc.mRemotePayloadType);
|
mActiveStream->setTransmittingCodec(*rc.mFactory, rc.mRemotePayloadType);
|
||||||
dynamic_cast<MT::AudioStream*>(mActiveStream.get())->setTelephoneCodec(mRemoteTelephoneCodec);
|
dynamic_cast<MT::AudioStream*>(mActiveStream.get())->setTelephoneCodec(mRemoteTelephoneCodec);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioProvider::setSocket(const RtpPair<PDatagramSocket>& p4, const RtpPair<PDatagramSocket>& p6)
|
void AudioProvider::setSocket(const RtpPair<PDatagramSocket>& p4, const RtpPair<PDatagramSocket>& p6)
|
||||||
{
|
{
|
||||||
mSocket4 = p4;
|
mSocket4 = p4;
|
||||||
mSocket6 = p6;
|
mSocket6 = p6;
|
||||||
mActiveStream->setSocket(p4);
|
mActiveStream->setSocket(p4);
|
||||||
}
|
}
|
||||||
|
|
||||||
RtpPair<PDatagramSocket>& AudioProvider::socket(int family)
|
RtpPair<PDatagramSocket>& AudioProvider::socket(int family)
|
||||||
{
|
{
|
||||||
switch (family)
|
switch (family)
|
||||||
{
|
{
|
||||||
case AF_INET:
|
case AF_INET:
|
||||||
return mSocket4;
|
return mSocket4;
|
||||||
|
|
||||||
case AF_INET6:
|
case AF_INET6:
|
||||||
return mSocket6;
|
return mSocket6;
|
||||||
}
|
}
|
||||||
return mSocket4;
|
return mSocket4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool AudioProvider::processSdpOffer(const resip::SdpContents::Session::Medium& media, SdpDirection sdpDirection)
|
bool AudioProvider::processSdpOffer(const resip::SdpContents::Session::Medium& media, SdpDirection sdpDirection)
|
||||||
{
|
{
|
||||||
// Check if there is compatible codec
|
// Check if there is compatible codec
|
||||||
mAvailableCodecs.clear();
|
mAvailableCodecs.clear();
|
||||||
mRemoteTelephoneCodec = 0;
|
mRemoteTelephoneCodec = 0;
|
||||||
|
|
||||||
|
// Check if there is SDP at all
|
||||||
|
mRemoteNoSdp = media.codecs().empty();
|
||||||
|
if (mRemoteNoSdp)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// Update RFC2833 related information
|
||||||
|
findRfc2833(media.codecs());
|
||||||
|
|
||||||
|
// Use CodecListPriority mCodecPriority to work with codec priorities
|
||||||
|
int pt;
|
||||||
|
for (int localIndex=0; localIndex<mCodecPriority.count(mTerminal.codeclist()); localIndex++)
|
||||||
|
{
|
||||||
|
MT::Codec::Factory& factory = mCodecPriority.codecAt(mTerminal.codeclist(), localIndex);
|
||||||
|
|
||||||
|
if ((pt = factory.processSdp(media.codecs(), sdpDirection)) != -1)
|
||||||
|
mAvailableCodecs.push_back(RemoteCodec(&factory, pt));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!mAvailableCodecs.size())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Iterate SRTP crypto: attributes
|
||||||
|
if (media.exists("crypto"))
|
||||||
|
{
|
||||||
|
// Find the most strong crypt suite
|
||||||
|
const std::list<resip::Data>& vl = media.getValues("crypto");
|
||||||
|
SrtpSuite ss = SRTP_NONE;
|
||||||
|
ByteBuffer key;
|
||||||
|
for (std::list<resip::Data>::const_iterator attrIter = vl.begin(); attrIter != vl.end(); attrIter++)
|
||||||
|
{
|
||||||
|
const resip::Data& attr = *attrIter;
|
||||||
|
ByteBuffer tempkey;
|
||||||
|
SrtpSuite suite = processCryptoAttribute(attr, tempkey);
|
||||||
|
if (suite > ss)
|
||||||
|
{
|
||||||
|
ss = suite;
|
||||||
|
mSrtpSuite = suite;
|
||||||
|
key = tempkey;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If SRTP suite is agreed
|
||||||
|
if (ss != SRTP_NONE)
|
||||||
|
{
|
||||||
|
ICELogInfo(<< "Found SRTP suite " << ss);
|
||||||
|
mActiveStream->srtp().open(key, ss);
|
||||||
|
setState(state() | (int)StreamState::Srtp);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
ICELogInfo(<< "Did not find valid SRTP suite");
|
||||||
|
}
|
||||||
|
|
||||||
|
DataProvider::processSdpOffer(media, sdpDirection);
|
||||||
|
|
||||||
// Check if there is SDP at all
|
|
||||||
mRemoteNoSdp = media.codecs().empty();
|
|
||||||
if (mRemoteNoSdp)
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
// Update RFC2833 related information
|
|
||||||
findRfc2833(media.codecs());
|
|
||||||
|
|
||||||
// Use CodecListPriority mCodecPriority to work with codec priorities
|
|
||||||
int pt;
|
|
||||||
for (int localIndex=0; localIndex<mCodecPriority.count(mTerminal.codeclist()); localIndex++)
|
|
||||||
{
|
|
||||||
MT::Codec::Factory& factory = mCodecPriority.codecAt(mTerminal.codeclist(), localIndex);
|
|
||||||
|
|
||||||
if ((pt = factory.processSdp(media.codecs(), sdpDirection)) != -1)
|
|
||||||
mAvailableCodecs.push_back(RemoteCodec(&factory, pt));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!mAvailableCodecs.size())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Iterate SRTP crypto: attributes
|
|
||||||
if (media.exists("crypto"))
|
|
||||||
{
|
|
||||||
// Find the most strong crypt suite
|
|
||||||
const std::list<resip::Data>& vl = media.getValues("crypto");
|
|
||||||
SrtpSuite ss = SRTP_NONE;
|
|
||||||
ByteBuffer key;
|
|
||||||
for (std::list<resip::Data>::const_iterator attrIter = vl.begin(); attrIter != vl.end(); attrIter++)
|
|
||||||
{
|
|
||||||
const resip::Data& attr = *attrIter;
|
|
||||||
ByteBuffer tempkey;
|
|
||||||
SrtpSuite suite = processCryptoAttribute(attr, tempkey);
|
|
||||||
if (suite > ss)
|
|
||||||
{
|
|
||||||
ss = suite;
|
|
||||||
mSrtpSuite = suite;
|
|
||||||
key = tempkey;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If SRTP suite is agreed
|
|
||||||
if (ss != SRTP_NONE)
|
|
||||||
{
|
|
||||||
ICELogInfo(<< "Found SRTP suite " << ss);
|
|
||||||
mActiveStream->srtp().open(key, ss);
|
|
||||||
setState(state() | (int)StreamState::Srtp);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
ICELogInfo(<< "Did not find valid SRTP suite");
|
|
||||||
}
|
|
||||||
|
|
||||||
DataProvider::processSdpOffer(media, sdpDirection);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioProvider::setState(unsigned state)
|
void AudioProvider::setState(unsigned state)
|
||||||
{
|
{
|
||||||
mState = state;
|
mState = state;
|
||||||
if (mActiveStream)
|
if (mActiveStream)
|
||||||
mActiveStream->setState(state);
|
mActiveStream->setState(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned AudioProvider::state()
|
unsigned AudioProvider::state()
|
||||||
{
|
{
|
||||||
return mState;
|
return mState;
|
||||||
}
|
}
|
||||||
|
|
||||||
MT::Statistics AudioProvider::getStatistics()
|
MT::Statistics AudioProvider::getStatistics()
|
||||||
{
|
{
|
||||||
if (mActiveStream)
|
if (mActiveStream)
|
||||||
return mActiveStream->statistics();
|
return mActiveStream->statistics();
|
||||||
else
|
else
|
||||||
return mBackupStats;
|
return mBackupStats;
|
||||||
}
|
}
|
||||||
|
|
||||||
MT::PStream AudioProvider::activeStream()
|
MT::PStream AudioProvider::activeStream()
|
||||||
{
|
{
|
||||||
return mActiveStream;
|
return mActiveStream;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string AudioProvider::createCryptoAttribute(SrtpSuite suite)
|
std::string AudioProvider::createCryptoAttribute(SrtpSuite suite)
|
||||||
{
|
{
|
||||||
if (!mActiveStream)
|
if (!mActiveStream)
|
||||||
return "";
|
return "";
|
||||||
|
|
||||||
// Use tag 1 - it is ok, as we use only single crypto attribute
|
// Use tag 1 - it is ok, as we use only single crypto attribute
|
||||||
int srtpTag = 1;
|
int srtpTag = 1;
|
||||||
|
|
||||||
// Print key to base64 string
|
// Print key to base64 string
|
||||||
PByteBuffer keyBuffer = mActiveStream->srtp().outgoingKey(suite).first;
|
PByteBuffer keyBuffer = mActiveStream->srtp().outgoingKey(suite).first;
|
||||||
resip::Data d(keyBuffer->data(), keyBuffer->size());
|
resip::Data d(keyBuffer->data(), keyBuffer->size());
|
||||||
resip::Data keyText = d.base64encode();
|
resip::Data keyText = d.base64encode();
|
||||||
|
|
||||||
// Create "crypto" attribute value
|
// Create "crypto" attribute value
|
||||||
char buffer[512];
|
char buffer[512];
|
||||||
const char* suiteName = NULL;
|
const char* suiteName = NULL;
|
||||||
switch (suite)
|
switch (suite)
|
||||||
{
|
{
|
||||||
case SRTP_AES_128_AUTH_80: suiteName = SRTP_SUITE_NAME_1; break;
|
case SRTP_AES_128_AUTH_80: suiteName = SRTP_SUITE_NAME_1; break;
|
||||||
case SRTP_AES_256_AUTH_80: suiteName = SRTP_SUITE_NAME_2; break;
|
case SRTP_AES_256_AUTH_80: suiteName = SRTP_SUITE_NAME_2; break;
|
||||||
default: assert(0);
|
default: assert(0);
|
||||||
}
|
}
|
||||||
sprintf(buffer, "%d %s inline:%s", srtpTag, suiteName, keyText.c_str());
|
sprintf(buffer, "%d %s inline:%s", srtpTag, suiteName, keyText.c_str());
|
||||||
|
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
SrtpSuite AudioProvider::processCryptoAttribute(const resip::Data& value, ByteBuffer& key)
|
SrtpSuite AudioProvider::processCryptoAttribute(const resip::Data& value, ByteBuffer& key)
|
||||||
{
|
{
|
||||||
int srtpTag = 0;
|
int srtpTag = 0;
|
||||||
char suite[64], keyChunk[256];
|
char suite[64], keyChunk[256];
|
||||||
int components = sscanf(value.c_str(), "%d %63s inline: %255s", &srtpTag, suite, keyChunk);
|
int components = sscanf(value.c_str(), "%d %63s inline: %255s", &srtpTag, suite, keyChunk);
|
||||||
if (components != 3)
|
if (components != 3)
|
||||||
return SRTP_NONE;
|
return SRTP_NONE;
|
||||||
|
|
||||||
const char* delimiter = strchr(keyChunk, '|');
|
const char* delimiter = strchr(keyChunk, '|');
|
||||||
resip::Data keyText;
|
resip::Data keyText;
|
||||||
if (delimiter)
|
if (delimiter)
|
||||||
keyText = resip::Data(keyChunk, delimiter - keyChunk);
|
keyText = resip::Data(keyChunk, delimiter - keyChunk);
|
||||||
else
|
else
|
||||||
keyText = resip::Data(keyChunk);
|
keyText = resip::Data(keyChunk);
|
||||||
|
|
||||||
resip::Data rawkey = keyText.base64decode();
|
resip::Data rawkey = keyText.base64decode();
|
||||||
key = ByteBuffer(rawkey.c_str(), rawkey.size());
|
key = ByteBuffer(rawkey.c_str(), rawkey.size());
|
||||||
|
|
||||||
// Open srtp
|
// Open srtp
|
||||||
SrtpSuite result = SRTP_NONE;
|
SrtpSuite result = SRTP_NONE;
|
||||||
if (strcmp(suite, SRTP_SUITE_NAME_1) == 0)
|
if (strcmp(suite, SRTP_SUITE_NAME_1) == 0)
|
||||||
result = SRTP_AES_128_AUTH_80;
|
result = SRTP_AES_128_AUTH_80;
|
||||||
else
|
else
|
||||||
if (strcmp(suite, SRTP_SUITE_NAME_2) == 0)
|
if (strcmp(suite, SRTP_SUITE_NAME_2) == 0)
|
||||||
result = SRTP_AES_256_AUTH_80;
|
result = SRTP_AES_256_AUTH_80;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioProvider::findRfc2833(const resip::SdpContents::Session::Medium::CodecContainer& codecs)
|
void AudioProvider::findRfc2833(const resip::SdpContents::Session::Medium::CodecContainer& codecs)
|
||||||
{
|
{
|
||||||
resip::SdpContents::Session::Medium::CodecContainer::const_iterator codecIter;
|
resip::SdpContents::Session::Medium::CodecContainer::const_iterator codecIter;
|
||||||
for (codecIter = codecs.begin(); codecIter != codecs.end(); codecIter++)
|
for (codecIter = codecs.begin(); codecIter != codecs.end(); codecIter++)
|
||||||
{
|
{
|
||||||
if (strcmp("TELEPHONE-EVENT", codecIter->getName().c_str()) == 0 ||
|
if (strcmp("TELEPHONE-EVENT", codecIter->getName().c_str()) == 0 ||
|
||||||
strcmp("telephone-event", codecIter->getName().c_str()) == 0)
|
strcmp("telephone-event", codecIter->getName().c_str()) == 0)
|
||||||
mRemoteTelephoneCodec = codecIter->payloadType();
|
mRemoteTelephoneCodec = codecIter->payloadType();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioProvider::readFile(const Audio::PWavFileReader& stream, MT::Stream::MediaDirection direction)
|
void AudioProvider::readFile(const Audio::PWavFileReader& stream, MT::Stream::MediaDirection direction)
|
||||||
{
|
{
|
||||||
// Iterate stream list
|
// Iterate stream list
|
||||||
if (mActiveStream)
|
if (mActiveStream)
|
||||||
mActiveStream->readFile(stream, direction);
|
mActiveStream->readFile(stream, direction);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioProvider::writeFile(const Audio::PWavFileWriter& stream, MT::Stream::MediaDirection direction)
|
void AudioProvider::writeFile(const Audio::PWavFileWriter& stream, MT::Stream::MediaDirection direction)
|
||||||
{
|
{
|
||||||
if (mActiveStream)
|
if (mActiveStream)
|
||||||
mActiveStream->writeFile(stream, direction);
|
mActiveStream->writeFile(stream, direction);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioProvider::setupMirror(bool enable)
|
void AudioProvider::setupMirror(bool enable)
|
||||||
{
|
{
|
||||||
if (mActiveStream)
|
if (mActiveStream)
|
||||||
mActiveStream->setupMirror(enable);
|
mActiveStream->setupMirror(enable);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,24 +13,28 @@ add_definitions(-DHAVE_STDINT_H -DHAVE_UINT64_T)
|
||||||
|
|
||||||
if(CMAKE_SYSTEM MATCHES "Linux*")
|
if(CMAKE_SYSTEM MATCHES "Linux*")
|
||||||
add_definitions(-DHAVE_NETINET_IN_H)
|
add_definitions(-DHAVE_NETINET_IN_H)
|
||||||
endif(CMAKE_SYSTEM MATCHES "Linux*")
|
endif()
|
||||||
|
|
||||||
if(CMAKE_SYSTEM MATCHES "Darwin*")
|
if(CMAKE_SYSTEM MATCHES "Darwin*")
|
||||||
# OS X Specific flags
|
# OS X Specific flags
|
||||||
add_definitions(-DHAVE_NETINET_IN_H)
|
add_definitions(-DHAVE_NETINET_IN_H)
|
||||||
endif(CMAKE_SYSTEM MATCHES "Darwin*")
|
endif()
|
||||||
|
|
||||||
if (CMAKE_SYSTEM MATCHES "Win*")
|
if (CMAKE_SYSTEM MATCHES "Windows*")
|
||||||
# Windows Specific flags - MSVC expected
|
# Windows Specific flags - MSVC expected
|
||||||
add_definitions(-D_CRT_SECURE_NO_WARNINGS -DHAVE_WINSOCK2_H
|
add_definitions(-D_CRT_SECURE_NO_WARNINGS -DHAVE_WINSOCK2_H
|
||||||
-D_SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS -DUNICODE -D_UNICODE )
|
-D_SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS -DUNICODE -D_UNICODE )
|
||||||
endif(CMAKE_SYSTEM MATCHES "Win*")
|
endif()
|
||||||
|
|
||||||
add_library(media_lib ${MEDIA_LIB_SOURCES})
|
add_library(media_lib ${MEDIA_LIB_SOURCES})
|
||||||
|
|
||||||
target_include_directories(media_lib PRIVATE ../../libs/
|
target_include_directories(media_lib
|
||||||
../ ../../libs/srtp/include
|
PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../../libs/
|
||||||
../../libs/srtp/crypto/include
|
${CMAKE_CURRENT_SOURCE_DIR}/../
|
||||||
../../libs/webrtc)
|
${CMAKE_CURRENT_SOURCE_DIR}/../../libs/srtp/include
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/../../libs/srtp/crypto/include
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/../../libs/webrtc
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/../../libs/opus/include/
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -24,3 +24,5 @@ set (GSM_SOURCES
|
||||||
)
|
)
|
||||||
|
|
||||||
add_library(gsm_codec ${GSM_SOURCES})
|
add_library(gsm_codec ${GSM_SOURCES})
|
||||||
|
target_include_directories(gsm_codec PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
|
||||||
|
target_compile_definitions(gsm_codec PUBLIC HAS_STDLIB_H HAS_STRING_H)
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include "config.h"
|
//#include "config.h"
|
||||||
|
|
||||||
|
|
||||||
#ifdef HAS_STDLIB_H
|
#ifdef HAS_STDLIB_H
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include "config.h"
|
//#include "config.h"
|
||||||
|
|
||||||
#ifdef HAS_STRING_H
|
#ifdef HAS_STRING_H
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
|
||||||
|
|
@ -307,4 +307,11 @@ SET (RUTIL_SOURCES
|
||||||
|
|
||||||
|
|
||||||
add_library(resiprocate ${ARES_SOURCES} ${RUTIL_SOURCES} ${STACK_SOURCES} ${DUM_SOURCES})
|
add_library(resiprocate ${ARES_SOURCES} ${RUTIL_SOURCES} ${STACK_SOURCES} ${DUM_SOURCES})
|
||||||
|
|
||||||
|
target_include_directories(resiprocate PUBLIC
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/contrib/ares
|
||||||
|
/usr/local/include
|
||||||
|
)
|
||||||
|
target_compile_definitions(resiprocate PUBLIC -DUSE_ARES -DUSE_SSL)
|
||||||
#add_library(resiprocate_lite ${RUTIL_SOURCES} ${STACK_SOURCES})
|
#add_library(resiprocate_lite ${RUTIL_SOURCES} ${STACK_SOURCES})
|
||||||
|
|
|
||||||
|
|
@ -20,3 +20,8 @@ set (SPEEXDSP_SOURCES
|
||||||
)
|
)
|
||||||
|
|
||||||
add_library(speexdsp ${SPEEXDSP_SOURCES})
|
add_library(speexdsp ${SPEEXDSP_SOURCES})
|
||||||
|
target_compile_definitions(speexdsp PUBLIC -DUSE_KISS_FFT -DFIXED_POINT)
|
||||||
|
|
||||||
|
target_include_directories(speexdsp PRIVATE
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/libspeexdsp
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/include)
|
||||||
|
|
|
||||||
|
|
@ -35,3 +35,7 @@ set (SRTP_SOURCES
|
||||||
)
|
)
|
||||||
|
|
||||||
add_library(srtp ${SRTP_SOURCES})
|
add_library(srtp ${SRTP_SOURCES})
|
||||||
|
target_include_directories(srtp PUBLIC
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/include
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/crypto/include
|
||||||
|
)
|
||||||
|
|
|
||||||
|
|
@ -173,3 +173,9 @@ set (WEBRTC_SOURCES
|
||||||
)
|
)
|
||||||
|
|
||||||
add_library(webrtc ${WEBRTC_SOURCES})
|
add_library(webrtc ${WEBRTC_SOURCES})
|
||||||
|
|
||||||
|
target_include_directories(webrtc PUBLIC
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/signal_processing_library
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/utility
|
||||||
|
)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue