diff --git a/sflphone-common/src/audio/audiortp/AudioRtpRecordHandler.h b/sflphone-common/src/audio/audiortp/AudioRtpRecordHandler.h index 28ce2ed0882fcb68e665e6f3d5f091462a616d87..aff3f17409828235a79829a865de53f1a404ad83 100644 --- a/sflphone-common/src/audio/audiortp/AudioRtpRecordHandler.h +++ b/sflphone-common/src/audio/audiortp/AudioRtpRecordHandler.h @@ -50,6 +50,13 @@ namespace sfl static const int schedulingTimeout = 10000; static const int expireTimeout = 100000; +// G.722 VoIP is typically carried in RTP payload type 9.[2] Note that IANA records the clock rate for type 9 G.722 as 8 kHz +// (instead of 16 kHz), RFC3551[3] clarifies that this is due to a historical error and is retained in order to maintain backward +// compatibility. Consequently correct implementations represent the value 8,000 where required but encode and decode audio at 16 kHz. +static const int g722PayloadType = 9; +static const int g722RtpClockRate = 8000; +static const int g722RtpTimeincrement = 160; + class AudioRtpSessionException: public std::exception { virtual const char* what() const throw() { diff --git a/sflphone-common/src/audio/audiortp/AudioRtpSession.cpp b/sflphone-common/src/audio/audiortp/AudioRtpSession.cpp index 37459267195228a32bec33ffd6a93276a6e18bbc..cb2f716bdee008c296596133ff65f81508573623 100644 --- a/sflphone-common/src/audio/audiortp/AudioRtpSession.cpp +++ b/sflphone-common/src/audio/audiortp/AudioRtpSession.cpp @@ -72,7 +72,7 @@ AudioRtpSession::AudioRtpSession (ManagerImpl * manager, SIPCall * sipcall) : // static_cast<ost::DualRTPUDPIPv4Channel>(dso)->sendSocket->setTypeOfService(ost::Socket::tosLowDelay); // static_cast<ost::DualRTPChannel<ost::DualRTPUDPIPv4Channel> >(dso)->sendSocket->setTypeOfService(ost::Socket::tosLowDelay); - // setTypeOfService(tosEnhanced); + setTypeOfService(tosEnhanced); } AudioRtpSession::~AudioRtpSession() @@ -80,7 +80,7 @@ AudioRtpSession::~AudioRtpSession() _info ("AudioRtpSession: Delete AudioRtpSession instance"); try { - terminate(); + terminate(); } catch (...) { _debugException ("AudioRtpSession: Thread destructor didn't terminate correctly"); throw; @@ -133,7 +133,7 @@ void AudioRtpSession::setSessionMedia (AudioCodec* audioCodec) } else if (dynamic) { _debug ("AudioRtpSession: Setting dynamic payload format"); setPayloadFormat (ost::DynamicPayloadFormat ( (ost::PayloadType) payloadType, smplRate)); - } else if (dynamic && payloadType != 9) { + } else if (dynamic && payloadType != g722PayloadType) { _debug ("AudioRtpSession: Setting static payload format"); setPayloadFormat (ost::StaticPayloadFormat ( (ost::StaticPayloadType) payloadType)); } @@ -229,8 +229,6 @@ void AudioRtpSession::sendDtmfEvent (sfl::DtmfEvent *dtmf) bool AudioRtpSession::onRTPPacketRecv (ost::IncomingRTPPkt&) { - // _debug ("AudioRtpSession: onRTPPacketRecv"); - receiveSpeakerData (); return true; @@ -257,7 +255,6 @@ void AudioRtpSession::sendMicData() // putData put the data on RTP queue, sendImmediate bypass this queue putData (_timestamp, getMicDataEncoded(), compSize); - // sendData() } @@ -322,6 +319,7 @@ void AudioRtpSession::run () // Timestamp must be initialized randomly, already done when instantiating outgoing queue _timestamp = getCurrentTimestamp(); + /** int threadSleep = 0; if (getCodecSampleRate() != 0) { @@ -332,6 +330,7 @@ void AudioRtpSession::run () } TimerPort::setTimer (threadSleep); + */ // Set recording sampling rate _ca->setRecordingSmplRate (getCodecSampleRate()); @@ -347,8 +346,6 @@ void AudioRtpSession::run () timeout = getSchedulingTimeout(); } - // timeout = ; - _manager->getAudioLayerMutex()->enter(); // Send session @@ -389,7 +386,6 @@ void AudioRtpSession::run () timeout = 0; } - // receiveSpeakerData(); } _debug ("AudioRtpSession: Left main loop for call %s", _ca->getCallId().c_str()); diff --git a/sflphone-common/src/audio/audiortp/AudioRtpSession.h b/sflphone-common/src/audio/audiortp/AudioRtpSession.h index b948e5cf5a5ab4cd2b868d298e779e743751980a..46e8bc70ab8549eae3adea76273466c3434ce6a0 100644 --- a/sflphone-common/src/audio/audiortp/AudioRtpSession.h +++ b/sflphone-common/src/audio/audiortp/AudioRtpSession.h @@ -57,13 +57,6 @@ namespace sfl { -// G.722 VoIP is typically carried in RTP payload type 9.[2] Note that IANA records the clock rate for type 9 G.722 as 8 kHz -// (instead of 16 kHz), RFC3551[3] clarifies that this is due to a historical error and is retained in order to maintain backward -// compatibility. Consequently correct implementations represent the value 8,000 where required but encode and decode audio at 16 kHz. -static const int g722PayloadType = 9; -static const int g722RtpClockRate = 8000; -static const int g722RtpTimeincrement = 160; - // class AudioRtpSession : protected ost::Thread, public ost::TimerPort, public AudioRtpRecordHandler, public ost::TRTPSessionBase<ost::DualRTPUDPIPv4Channel,ost::DualRTPUDPIPv4Channel,ost::AVPQueue> class AudioRtpSession : protected ost::Thread, public ost::TimerPort, public AudioRtpRecordHandler, public ost::TRTPSessionBase<ost::SymmetricRTPChannel, ost::SymmetricRTPChannel, ost::AVPQueue> { diff --git a/sflphone-common/src/audio/audiortp/AudioZrtpSession.cpp b/sflphone-common/src/audio/audiortp/AudioZrtpSession.cpp index 7da895bfcc4d38567d1c7851fefcd0dece8cc6e7..14415cada4c40ab0de203912e04316b759ae6aa0 100644 --- a/sflphone-common/src/audio/audiortp/AudioZrtpSession.cpp +++ b/sflphone-common/src/audio/audiortp/AudioZrtpSession.cpp @@ -33,6 +33,7 @@ #include "sip/sipcall.h" #include "sip/sdp.h" #include "audio/audiolayer.h" +#include "manager.h" #include <libzrtpcpp/ZrtpQueue.h> #include <libzrtpcpp/ZrtpUserCallback.h> @@ -64,25 +65,27 @@ AudioZrtpSession::AudioZrtpSession (ManagerImpl * manager, SIPCall * sipcall, co assert (_ca); - _info ("AudioZrtpSession: Local audio port %i will be used", _ca->getLocalAudioPort()); + _info ("AudioZrtpSession: Setting new RTP session with destination %s:%d", _ca->getLocalIp().c_str(), _ca->getLocalAudioPort()); + + setTypeOfService(tosEnhanced); } AudioZrtpSession::~AudioZrtpSession() { _debug ("AudioZrtpSession: Delete AudioRtpSession instance"); - try { - terminate(); - } catch (...) { - _debugException ("AudioZrtpSession: Thread destructor didn't terminate correctly"); - throw; - } + try { + terminate(); + } catch (...) { + _debugException ("AudioZrtpSession: Thread destructor didn't terminate correctly"); + throw; + } - _manager->getAudioDriver()->getMainBuffer()->unBindAll (_ca->getCallId()); + _manager->getAudioDriver()->getMainBuffer()->unBindAll (_ca->getCallId()); - if(_time) - delete _time; - _time = NULL; + if(_time) + delete _time; + _time = NULL; } @@ -134,12 +137,16 @@ void AudioZrtpSession::initializeZid (void) void AudioZrtpSession::setSessionTimeouts (void) { + _debug("AudioZrtpSession: Set session scheduling timeout (%d) and expireTimeout (%d)", sfl::schedulingTimeout, sfl::expireTimeout); + setSchedulingTimeout (sfl::schedulingTimeout); setExpireTimeout (sfl::expireTimeout); } void AudioZrtpSession::setSessionMedia (AudioCodec* audioCodec) { + _debug("AudioRtpSession: Set session media"); + // set internal codec info for this session setRtpMedia(audioCodec); @@ -150,24 +157,25 @@ void AudioZrtpSession::setSessionMedia (AudioCodec* audioCodec) bool dynamic = getHasDynamicPayload(); // G722 requires timestamp to be incremented at 8 kHz - if (payloadType == 9) - _timestampIncrement = 160; + if (payloadType == g722PayloadType) + _timestampIncrement = g722RtpTimeincrement; else _timestampIncrement = frameSize; - _debug ("AudioRtpSession: Codec sampling rate: %d", smplRate); - _debug ("AudioRtpSession: Codec frame size: %d", frameSize); - _debug ("AudioRtpSession: RTP timestamp increment: %d", _timestampIncrement); + _debug ("AudioZrtpSession: Codec payload: %d", payloadType); + _debug ("AudioZrtpSession: Codec sampling rate: %d", smplRate); + _debug ("AudioZrtpSession: Codec frame size: %d", frameSize); + _debug ("AudioZrtpSession: RTP timestamp increment: %d", _timestampIncrement); // Even if specified as a 16 kHz codec, G722 requires rtp sending rate to be 8 kHz - if (payloadType == 9) { - _debug ("AudioRtpSession: Setting G722 payload format"); - setPayloadFormat (ost::DynamicPayloadFormat ( (ost::PayloadType) payloadType, smplRate)); + if (payloadType == g722PayloadType) { + _debug ("AudioZrtpSession: Setting G722 payload format"); + setPayloadFormat (ost::DynamicPayloadFormat ( (ost::PayloadType) payloadType, g722RtpClockRate)); } else if (dynamic) { - _debug ("AudioRtpSession: Setting dynamic payload format"); + _debug ("AudioZrtpSession: Setting dynamic payload format"); setPayloadFormat (ost::DynamicPayloadFormat ( (ost::PayloadType) payloadType, smplRate)); - } else if (dynamic && payloadType != 9) { - _debug ("AudioRtpSession: Setting static payload format"); + } else if (dynamic && payloadType != g722PayloadType) { + _debug ("AudioZrtpSession: Setting static payload format"); setPayloadFormat (ost::StaticPayloadFormat ( (ost::StaticPayloadType) payloadType)); } @@ -175,18 +183,18 @@ void AudioZrtpSession::setSessionMedia (AudioCodec* audioCodec) void AudioZrtpSession::setDestinationIpAddress (void) { + _info ("AudioZrtpSession: Setting IP address for the RTP session"); + if (_ca == NULL) { - _error ("AudioRtpSession: Sipcall is gone."); + _error ("AudioZrtpSession: Sipcall is gone."); throw AudioRtpSessionException(); } - _info ("AudioRtpSession: Setting IP address for the RTP session"); - // Store remote ip in case we would need to forget current destination _remote_ip = ost::InetHostAddress (_ca->getLocalSDP()->get_remote_ip().c_str()); if (!_remote_ip) { - _warn ("AudioRtpSession: Target IP address (%s) is not correct!", + _warn ("AudioZrtpSession: Target IP address (%s) is not correct!", _ca->getLocalSDP()->get_remote_ip().data()); return; } @@ -194,22 +202,24 @@ void AudioZrtpSession::setDestinationIpAddress (void) // Store remote port in case we would need to forget current destination _remote_port = (unsigned short) _ca->getLocalSDP()->get_remote_audio_port(); - _info ("AudioRtpSession: New remote address for session: %s:%d", + _info ("AudioZrtpSession: New remote address for session: %s:%d", _ca->getLocalSDP()->get_remote_ip().data(), _remote_port); if (!addDestination (_remote_ip, _remote_port)) { - _warn ("AudioRtpSession: Can't add new destination to session!"); + _warn ("AudioZrtpSession: Can't add new destination to session!"); return; } } void AudioZrtpSession::updateDestinationIpAddress (void) { + _debug("AudioZrtpSession: Update destination ip address"); + // Destination address are stored in a list in ccrtp // This method remove the current destination entry if (!forgetDestination (_remote_ip, _remote_port, _remote_port+1)) - _warn ("AudioRtpSession: Could not remove previous destination"); + _warn ("AudioZrtpSession: Could not remove previous destination"); // new destination is stored in call // we just need to recall this method @@ -218,7 +228,7 @@ void AudioZrtpSession::updateDestinationIpAddress (void) void AudioZrtpSession::sendDtmfEvent (sfl::DtmfEvent *dtmf) { - _debug ("AudioRtpSession: Send Dtmf %d", getEventQueueSize()); + _debug ("AudioZrtpSession: Send Dtmf %d", getEventQueueSize()); _timestamp += 160; @@ -258,9 +268,9 @@ void AudioZrtpSession::sendDtmfEvent (sfl::DtmfEvent *dtmf) } } -bool onRTPPacketRecv (ost::IncomingRTPPkt&) +bool AudioZrtpSession::onRTPPacketRecv (ost::IncomingRTPPkt&) { - _debug ("AudioRtpSession: onRTPPacketRecv"); + receiveSpeakerData(); return true; } @@ -268,10 +278,23 @@ bool onRTPPacketRecv (ost::IncomingRTPPkt&) void AudioZrtpSession::sendMicData() { + int compSize = processDataEncode(); + + // if no data return + if(!compSize) + return; + // Increment timestamp for outgoing packet _timestamp += _timestampIncrement; - int compSize = processDataEncode(); + // Reset timestamp to make sure the timing information are up to date + if (_timestampCount > RTP_TIMESTAMP_RESET_FREQ) { + _timestamp = getCurrentTimestamp(); + _timestampCount = 0; + } + + // Increment timestamp for outgoing packet + _timestamp += _timestampIncrement; // putData put the data on RTP queue, sendImmediate bypass this queue putData (_timestamp, getMicDataEncoded(), compSize); @@ -293,14 +316,8 @@ void AudioZrtpSession::receiveSpeakerData () unsigned char* spkrDataIn = NULL; unsigned int size = 0; - if (adu) { - - spkrDataIn = (unsigned char*) adu->getData(); // data in char - size = adu->getSize(); // size in char - - } else { - _debug ("AudioRtpSession: No RTP packet available"); - } + spkrDataIn = (unsigned char*) adu->getData(); // data in char + size = adu->getSize(); // size in char // DTMF over RTP, size must be over 4 in order to process it as voice data if (size > 4) { @@ -310,14 +327,32 @@ void AudioZrtpSession::receiveSpeakerData () delete adu; } +void AudioZrtpSession::notifyIncomingCall() +{ + // Notify (with a beep) an incoming call when there is already a call + if (Manager::instance().incomingCallWaiting() > 0) { + _countNotificationTime += _time->getSecond(); + int countTimeModulo = _countNotificationTime % 5000; + + if ( (countTimeModulo - _countNotificationTime) < 0) { + Manager::instance().notificationIncomingCall(); + } + _countNotificationTime = countTimeModulo; + } +} int AudioZrtpSession::startRtpThread (AudioCodec* audiocodec) { - _debug ("RTP: Starting main thread"); + _debug ("AudioZrtpSession: Starting main thread"); setSessionTimeouts(); setSessionMedia (audiocodec); initBuffers(); - return start (_mainloopSemaphore); + initNoiseSuppress(); + enableStack(); + + int ret = start(_mainloopSemaphore); + + return ret; } void AudioZrtpSession::run () @@ -335,8 +370,6 @@ void AudioZrtpSession::run () threadSleep = getAudioLayerFrameSize(); } - initNoiseSuppress(); - TimerPort::setTimer (threadSleep); // Set recording sampling rate @@ -344,9 +377,8 @@ void AudioZrtpSession::run () // Start audio stream (if not started) AND flush all buffers (main and urgent) _manager->getAudioDriver()->startStream(); - startRunning(); - _debug ("AudioRtpSession: Entering mainloop for call %s",_ca->getCallId().c_str()); + _debug ("AudioZrtpSession: Entering mainloop for call %s",_ca->getCallId().c_str()); while (!testCancel()) { @@ -384,7 +416,7 @@ void AudioZrtpSession::run () TimerPort::incTimer (threadSleep); } - _debug ("AudioRtpSession: Left main loop for call %s", _ca->getCallId().c_str()); + _debug ("AudioZrtpSession: Left main loop for call %s", _ca->getCallId().c_str()); } } diff --git a/sflphone-common/src/audio/audiortp/AudioZrtpSession.h b/sflphone-common/src/audio/audiortp/AudioZrtpSession.h index 8cc55312239835eae3a0f475d8b5a562743e30cd..91c77019e7691a856e7d71e8e900f6cef0a85abc 100644 --- a/sflphone-common/src/audio/audiortp/AudioZrtpSession.h +++ b/sflphone-common/src/audio/audiortp/AudioZrtpSession.h @@ -57,6 +57,8 @@ class AudioZrtpSession : public ost::TimerPort, public ost::SymmetricZRTPSession // Thread associated method virtual void run (); + virtual bool onRTPPacketRecv (ost::IncomingRTPPkt&); + int startRtpThread (AudioCodec*); /** @@ -92,6 +94,8 @@ class AudioZrtpSession : public ost::TimerPort, public ost::SymmetricZRTPSession void setDestinationIpAddress (void); + void notifyIncomingCall(); + /** * Send encoded data to peer */