diff --git a/sflphone-common/src/audio/audiortp.cpp b/sflphone-common/src/audio/audiortp.cpp deleted file mode 100644 index 26615888a789d5b863c2a3e9f284fca381e2b458..0000000000000000000000000000000000000000 --- a/sflphone-common/src/audio/audiortp.cpp +++ /dev/null @@ -1,685 +0,0 @@ -/* - * Copyright (C) 2004-2008 Savoir-Faire Linux inc. - * Author: Emmanuel Milou <emmanuel.milou@savoirfairelinux.com> - * Author: Alexandre Bourget <alexandre.bourget@savoirfairelinux.com> - * Author: Yan Morin <yan.morin@savoirfairelinux.com> - * Author: Laurielle Lea <laurielle.lea@savoirfairelinux.com> - * Author: Alexandre Savard <alexandre.savard@savoirfairelinux.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include <cstdio> -#include <cstdlib> -#include <ccrtp/rtp.h> -#include <assert.h> -#include <cstring> -#include <math.h> -#include <dlfcn.h> -#include <iostream> -#include <sstream> - -#include "../global.h" -#include "../manager.h" -#include "codecDescriptor.h" -#include "audiortp.h" -#include "audiolayer.h" -#include "ringbuffer.h" -#include "../user_cfg.h" -#include "../sipcall.h" - - -int AudioRtpRTX::count_rtp = 0; - -//////////////////////////////////////////////////////////////////////////////// -// AudioRtp -//////////////////////////////////////////////////////////////////////////////// -AudioRtp::AudioRtp() :_RTXThread (0), _symmetric(), _rtpMutex() -{ - -} - -AudioRtp::~AudioRtp (void) -{ - ost::MutexLock m (_rtpMutex); - - if (_RTXThread != _RTXThread) { - delete _RTXThread; - _RTXThread = 0; - } - -} - -void -AudioRtp::createNewSession (SIPCall *ca) -{ - - ost::MutexLock m (_rtpMutex); - - _debug ("AudioRtp::Create new rtp session"); - - // something should stop the thread before... - - if (_RTXThread != 0) { - _debug ("**********************************************************"); - _debug ("! ARTP Failure: Thread already exists..., stopping it"); - _debug ("**********************************************************"); - delete _RTXThread; - _RTXThread = 0; - } - - // Start RTP Send/Receive threads - _symmetric = Manager::instance().getConfigInt (SIGNALISATION,SYMMETRIC) ? true : false; - - _RTXThread = new AudioRtpRTX (ca, _symmetric); - -} - -int -AudioRtp::start (void) -{ - ost::MutexLock m (_rtpMutex); - - if (_RTXThread == 0) { - _debug ("! ARTP Failure: Cannot start audiortp thread since not yet created"); - throw AudioRtpException(); - } - - - try { - if (_RTXThread->start() != 0) { - _debug ("! ARTP Failure: unable to start RTX Thread"); - return -1; - } - } catch (...) { - _debugException ("! ARTP Failure: when trying to start a thread"); - throw; - } - - return 0; -} - - -bool -AudioRtp::closeRtpSession () -{ - - ost::MutexLock m (_rtpMutex); - // This will make RTP threads finish. - _debug ("AudioRtp::Stopping rtp session"); - - try { - if (_RTXThread != 0) { - delete _RTXThread; - _RTXThread = 0; - } - } catch (...) { - _debugException ("! ARTP Exception: when stopping audiortp"); - throw; - } - - _debug ("AudioRtp::Audio rtp stopped"); - - return true; -} - -/* -void -AudioRtp::setRecording() -{ - - _debug ("AudioRtp::setRecording"); - _RTXThread->_ca->setRecording(); - -} -*/ - -//////////////////////////////////////////////////////////////////////////////// -// AudioRtpRTX Class // -//////////////////////////////////////////////////////////////////////////////// -AudioRtpRTX::AudioRtpRTX (SIPCall *sipcall, bool sym) : time (new ost::Time()), _ca (sipcall), _sessionSend (NULL), _sessionRecv (NULL), _session (NULL), - _sym (sym), micData (NULL), micDataConverted (NULL), micDataEncoded (NULL), spkrDataDecoded (NULL), spkrDataConverted (NULL), - converter (NULL), _layerSampleRate(),_codecSampleRate(), _layerFrameSize(), _audiocodec (NULL) -{ - - setCancel (cancelDefault); - // AudioRtpRTX should be close if we change sample rate - // TODO: Change bind address according to user settings. - // TODO: this should be the local ip not the external (router) IP - std::string localipConfig = _ca->getLocalIp(); // _ca->getLocalIp(); - ost::InetHostAddress local_ip (localipConfig.c_str()); - - _debug ("%i", _ca->getLocalAudioPort()); - _session = new ost::SymmetricRTPSession (local_ip, _ca->getLocalAudioPort()); - // _session = new ost::RTPSessionBase(local_ip, _ca->getLocalAudioPort()); - _sessionRecv = NULL; - _sessionSend = NULL; - - //mic, we receive from soundcard in stereo, and we send encoded - //encoding before sending - _audiolayer = Manager::instance().getAudioDriver(); - _layerFrameSize = _audiolayer->getFrameSize(); // in ms - _layerSampleRate = _audiolayer->getSampleRate(); - - // initBuffers(); - - // initAudioRtpSession(); - - _payloadIsSet = false; - _remoteIpIsSet = false; - - - count_rtp++; - // open files - std::string s_input; - std::string s_output; - - // convert count into string - std::stringstream out; - out << count_rtp; - - s_input = "/home/alexandresavard/Desktop/buffer_record/rtp_input_"; - s_input.append (out.str()); - - s_output = "/home/alexandresavard/Desktop/buffer_record/rtp_output_"; - s_output.append (out.str()); - - rtp_input_rec = new std::fstream(); - rtp_output_rec = new std::fstream(); - - rtp_input_rec->open (s_input.c_str(), std::fstream::out); - rtp_output_rec->open (s_output.c_str(), std::fstream::out); - -} - -AudioRtpRTX::~AudioRtpRTX () -{ - - ost::MutexLock m (_rtpRtxMutex); - - _debug ("Delete AudioRtpRTX instance in callid %s", _ca->getCallId().c_str()); - - try { - this->terminate(); - } catch (...) { - _debugException ("! ARTP: Thread destructor didn't terminate correctly"); - throw; - } - - _debug ("Remove audio stream for call id %s", _ca->getCallId().c_str()); - - _audiolayer->getMainBuffer()->unBindAll (_ca->getCallId()); - // Manager::instance().removeStream(_ca->getCallId()); - - _debug ("DELETE print micData address %p", micData); - delete [] micData; - micData = NULL; - delete [] micDataConverted; - micDataConverted = NULL; - delete [] micDataEncoded; - micDataEncoded = NULL; - - delete [] spkrDataDecoded; - spkrDataDecoded = NULL; - delete [] spkrDataConverted; - spkrDataConverted = NULL; - - delete time; - time = NULL; - - delete converter; - converter = NULL; - - _ca = 0; - // _session->terminate(); - - delete _session; - _session = NULL; - - _debug ("AudioRtpRTX instance deleted"); - - rtp_input_rec->close(); - rtp_output_rec->close(); - -} - - -void -AudioRtpRTX::initBuffers() -{ - ost::MutexLock m (_rtpRtxMutex); - - _debug ("AudioRtpRTX::initBuffers Init RTP buffers for %s", _ca->getCallId().c_str()); - - converter = new SamplerateConverter (_layerSampleRate , _layerFrameSize); - - nbSamplesMax = (int) (_layerSampleRate * _layerFrameSize /1000); - - - _debug ("AudioRtpRTX::initBuffers NBSAMPLEMAX %i", nbSamplesMax); - - micData = new SFLDataFormat[nbSamplesMax]; - _debug ("CREATE print micData address %p", micData); - micDataConverted = new SFLDataFormat[nbSamplesMax]; - micDataEncoded = new unsigned char[nbSamplesMax]; - - spkrDataConverted = new SFLDataFormat[nbSamplesMax]; - spkrDataDecoded = new SFLDataFormat[nbSamplesMax]; - - Manager::instance().addStream (_ca->getCallId()); - // _audiolayer->getMainBuffer()->bindCallID(_ca->getCallId()); -} - - -void -AudioRtpRTX::initAudioRtpSession (void) -{ - - try { - - _session->setSchedulingTimeout (100000); - _session->setExpireTimeout (1000000); - - - } catch (...) { - _debugException ("! ARTP Failure: initialisation failed"); - throw; - } - -} - -void -AudioRtpRTX::setRtpSessionMedia (void) -{ - - if (_ca == 0) { - _debug (" !ARTP: No call, can't init RTP media"); - return; - } - - AudioCodecType pl = (AudioCodecType) _ca->getLocalSDP()->get_session_media()->getPayload(); - - _audiocodec = Manager::instance().getCodecDescriptorMap().instantiateCodec (pl); - - if (_audiocodec == NULL) { - _debug (" !ARTP: No audiocodec, can't init RTP media"); - return; - } - - _debug ("Init audio RTP session: codec payload %i", _audiocodec->getPayload()); - - // _audioCodecInstance = *_audiocodec; - - _codecSampleRate = _audiocodec->getClockRate(); - - _codecFrameSize = _audiocodec->getFrameSize(); - - if (_audiocodec->getPayload() == 9) { - _payloadIsSet = _session->setPayloadFormat (ost::DynamicPayloadFormat ( (ost::PayloadType) _audiocodec->getPayload(), _audiocodec->getClockRate())); - } else if (_audiocodec->hasDynamicPayload()) { - _payloadIsSet = _session->setPayloadFormat (ost::DynamicPayloadFormat ( (ost::PayloadType) _audiocodec->getPayload(), _audiocodec->getClockRate())); - } else if (!_audiocodec->hasDynamicPayload() && _audiocodec->getPayload() != 9) { - _payloadIsSet = _session->setPayloadFormat (ost::StaticPayloadFormat ( (ost::StaticPayloadType) _audiocodec->getPayload())); - } - - - -} - -void -AudioRtpRTX::setRtpSessionRemoteIp (void) -{ - - if (!_remoteIpIsSet) { - - _debug ("++++++++++++++++++++++++++ SET IP ADDRESS ++++++++++++++++++++++++++++"); - - if (_ca == 0) { - _debug (" !ARTP: No call, can't init RTP media "); - return; - } - - ost::InetHostAddress remote_ip (_ca->getLocalSDP()->get_remote_ip().c_str()); - - _debug ("Init audio RTP session: remote ip %s", _ca->getLocalSDP()->get_remote_ip().data()); - - if (!remote_ip) { - _debug (" !ARTP Thread Error: Target IP address [%s] is not correct!", _ca->getLocalSDP()->get_remote_ip().data()); - return; - } - - _debug ("++++Address: %s, audioport: %d", _ca->getLocalSDP()->get_remote_ip().c_str(), _ca->getLocalSDP()->get_remote_audio_port()); - - _debug ("++++Audioport: %d", (int) _ca->getLocalSDP()->get_remote_audio_port()); - - if (!_session->addDestination (remote_ip, (unsigned short) _ca->getLocalSDP()->get_remote_audio_port())) { - _debug (" !ARTP Thread Error: can't add destination to session!"); - return; - } - - _remoteIpIsSet = true; - } else { - _debug ("+++++++++++++++++++++++ IP ADDRESS ALREADY SET ++++++++++++++++++++++++"); - } - -} - - - -float -AudioRtpRTX::computeCodecFrameSize (int codecSamplePerFrame, int codecClockRate) -{ - return ( (float) codecSamplePerFrame * 1000.0) / (float) codecClockRate; -} - -int -AudioRtpRTX::computeNbByteAudioLayer (float codecFrameSize) -{ - return (int) ( (float) _layerSampleRate * codecFrameSize * (float) sizeof (SFLDataFormat) / 1000.0); -} - - -int -AudioRtpRTX::processDataEncode() -{ - - // compute codec framesize in ms - float fixed_codec_framesize = computeCodecFrameSize (_audiocodec->getFrameSize(), _audiocodec->getClockRate()); - - // compute nb of byte to get coresponding to 20 ms at audio layer frame size (44.1 khz) - int maxBytesToGet = computeNbByteAudioLayer (fixed_codec_framesize); - - // available bytes inside ringbuffer - int availBytesFromMic = _audiolayer->getMainBuffer()->availForGet (_ca->getCallId()); - - // _debug("AudioRtpRTX::processDataEncode() callid: %s availBytesFromMic %i", _ca->getCallId().c_str(), availBytesFromMic); - - // _debug("AudioRtpRTX::processDataEncode: availBytesFromMic: %i", availBytesFromMic); - // set available byte to maxByteToGet - int bytesAvail = (availBytesFromMic < maxBytesToGet) ? availBytesFromMic : maxBytesToGet; - // _debug("bytesAvail %i", bytesAvail); - - if (bytesAvail == 0) - return 0; - - // _debug("AudioRtpRTX::processDataEncode: bytesAvail: %i", bytesAvail); - // Get bytes from micRingBuffer to data_from_mic - int nbSample = _audiolayer->getMainBuffer()->getData (micData , bytesAvail, 100, _ca->getCallId()) / sizeof (SFLDataFormat); - - rtp_output_rec->write ( (char*) micData, bytesAvail); - - // _debug("AudioRtpRTX::processDataEncode: nbSample: %i", nbSample); - - // nb bytes to be sent over RTP - int compSize = 0; - - // test if resampling is required - if (_audiocodec->getClockRate() != _layerSampleRate) { - - int nb_sample_up = nbSample; - //_debug("_nbSample audiolayer->getMic(): %i ", nbSample); - - // Store the length of the mic buffer in samples for recording - _nSamplesMic = nbSample; - - nbSample = reSampleData (micData , micDataConverted, _audiocodec->getClockRate(), nb_sample_up, DOWN_SAMPLING); - - compSize = _audiocodec->codecEncode (micDataEncoded, micDataConverted, nbSample*sizeof (int16)); - - } else { - // no resampling required - compSize = _audiocodec->codecEncode (micDataEncoded, micData, nbSample*sizeof (int16)); - } - - return compSize; -} - - -void -AudioRtpRTX::processDataDecode (unsigned char* spkrData, unsigned int size, int& countTime) -{ - if (_audiocodec != NULL) { - - // Return the size of data in bytes - int expandedSize = _audiocodec->codecDecode (spkrDataDecoded , spkrData , size); - - // buffer _receiveDataDecoded ----> short int or int16, coded on 2 bytes - int nbSample = expandedSize / sizeof (SFLDataFormat); - - // test if resampling is required - - if (_audiocodec->getClockRate() != _layerSampleRate) { - - // Do sample rate conversion - int nb_sample_down = nbSample; - nbSample = reSampleData (spkrDataDecoded, spkrDataConverted, _codecSampleRate, nb_sample_down, UP_SAMPLING); - - rtp_input_rec->write ( (char*) spkrDataConverted, nbSample * sizeof (SFLDataFormat)); - - // Store the number of samples for recording - _nSamplesSpkr = nbSample; - - - - // put data in audio layer, size in byte - _audiolayer->getMainBuffer()->putData (spkrDataConverted, nbSample * sizeof (SFLDataFormat), 100, _ca->getCallId()); - - } else { - - // Stor the number of samples for recording - _nSamplesSpkr = nbSample; - - // put data in audio layer, size in byte - _audiolayer->getMainBuffer()->putData (spkrDataDecoded, nbSample * sizeof (SFLDataFormat), 100, _ca->getCallId()); - } - - // Notify (with a beep) an incoming call when there is already a call - countTime += time->getSecond(); - - if (Manager::instance().incomingCallWaiting() > 0) { - countTime = countTime % 500; // more often... - - if (countTime == 0) { - Manager::instance().notificationIncomingCall(); - } - } - - } else { - countTime += time->getSecond(); - } -} - -void -AudioRtpRTX::sendSessionFromMic (int timestamp) -{ - // STEP: - // 1. get data from mic - // 2. convert it to int16 - good sample, good rate - // 3. encode it - // 4. send it - - timestamp += time->getSecond(); - // no call, so we do nothing - - if (_ca==0) { - _debug (" !ARTP: No call associated (mic)"); - return; - } - - // AudioLayer* audiolayer = Manager::instance().getAudioDriver(); - if (!_audiolayer) { - _debug (" !ARTP: No audiolayer available for MIC"); - return; - } - - if (!_audiocodec) { - _debug (" !ARTP: No audiocodec available for MIC"); - return; - } - - - - int compSize = processDataEncode(); - - // putData put the data on RTP queue, sendImmediate bypass this queue - // _debug("AudioRtpRTX::sendSessionFromMic: timestamp: %i, compsize: %i", timestamp, compSize); - - if ( (compSize != 0) && (micDataEncoded != NULL)) - _session->putData (timestamp, micDataEncoded, compSize); - - // _session->sendImmediate(timestamp, micDataEncoded, compSize); - - -} - - -void -AudioRtpRTX::receiveSessionForSpkr (int& countTime) -{ - - if (_ca == 0) { - return; - } - - if (!_audiolayer) { - _debug (" !ARTP: No audiolayer available for SPEAKER"); - return; - } - - if (!_audiocodec) { - _debug (" !ARTP: No audiocodec available for SPEAKER"); - return; - } - - const ost::AppDataUnit* adu = NULL; - - // int is_waiting = _session->isWaiting(); - - // if (is_waiting != 0) - adu = _session->getData (_session->getFirstTimestamp()); - - // else - // return; - - - - if (adu == NULL) - return; - - unsigned char* spkrData = (unsigned char*) adu->getData(); // data in char - - unsigned int size = adu->getSize(); // size in char - - processDataDecode (spkrData, size, countTime); - - if (adu != NULL) { - delete adu; - adu = NULL; - } - -} - - -int -AudioRtpRTX::reSampleData (SFLDataFormat *input, SFLDataFormat *output, int sampleRate_codec, int nbSamples, int status) -{ - if (status==UP_SAMPLING) { - return converter->upsampleData (input, output, sampleRate_codec , _layerSampleRate , nbSamples); - } else if (status==DOWN_SAMPLING) { - return converter->downsampleData (micData , micDataConverted , sampleRate_codec , _layerSampleRate , nbSamples); - } else - - return 0; -} - - - -void -AudioRtpRTX::run () -{ - - int sessionWaiting; - - initBuffers(); - initAudioRtpSession(); - setRtpSessionRemoteIp(); - setRtpSessionMedia(); - - int timestep = _codecFrameSize; - - int countTime = 0; // for receive - - int threadSleep = 0; - - if (_codecSampleRate != 0) - threadSleep = (_codecFrameSize * 1000) / _codecSampleRate; - else - threadSleep = _layerFrameSize; - - TimerPort::setTimer (threadSleep); - - _audiolayer->startStream(); - - _audiolayer->getMainBuffer()->flush (_ca->getCallId()); - - _session->startRunning(); - - int timestamp = _session->getCurrentTimestamp(); // for mic - - _debug ("- ARTP Action: Start call %s",_ca->getCallId().c_str()); - - while (!testCancel()) { - - - // _debug("Main while loop for call: %s", _ca->getCallId().c_str()); - // Send session - sessionWaiting = _session->isWaiting(); - - sendSessionFromMic (timestamp); - timestamp += timestep; - // timestamp = _session->getCurrentTimestamp(); - - // Recv session - receiveSessionForSpkr (countTime); - - // Let's wait for the next transmit cycle - - - if (sessionWaiting == 1) { - // Record mic and speaker during conversation - _ca->recAudio.recData (spkrDataConverted,micData,_nSamplesSpkr,_nSamplesMic); - } else { - // Record mic only while leaving a message - _ca->recAudio.recData (micData,_nSamplesMic); - } - - - // Let's wait for the next transmit cycle - Thread::sleep (TimerPort::getTimer()); - - - // TimerPort::incTimer(20); // 'frameSize' ms - TimerPort::incTimer (threadSleep); - - } - - // _audiolayer->stopStream(); - _debug ("- ARTP Action: Stop call %s",_ca->getCallId().c_str()); - - -} - - -// EOF diff --git a/sflphone-common/src/audio/audiortp.h b/sflphone-common/src/audio/audiortp.h deleted file mode 100644 index f9dc1671a9297b15cd79bab4a537b456340a370d..0000000000000000000000000000000000000000 --- a/sflphone-common/src/audio/audiortp.h +++ /dev/null @@ -1,299 +0,0 @@ -/* - * Copyright (C) 2004-2008 Savoir-Faire Linux inc. - * Author: Emmanuel Milou <emmanuel.milou@savoirfairelinux.com> - * Author: Alexandre Bourget <alexandre.bourget@savoirfairelinux.com> - * Author: Alexandre Savard <alexandre.savard@savoirfairelinux.com> - * Author: Yan Morin <yan.morin@savoirfairelinux.com> - * Author: Laurielle Lea <laurielle.lea@savoirfairelinux.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef __AUDIO_RTP_H__ -#define __AUDIO_RTP_H__ - -#include <cstdio> -#include <cstdlib> -#include <iostream> -#include <ccrtp/rtp.h> -#include <cc++/numbers.h> - -#include "../global.h" -// #include "plug-in/audiorecorder/audiorecord.h" -#include "../samplerateconverter.h" -#include "codecDescriptor.h" - -#include <fstream> - -#define UP_SAMPLING 0 -#define DOWN_SAMPLING 1 - - - -class AudioRtpException: public std::exception -{ - virtual const char* what() const throw() - { - return "AudioRtpException occured"; - } -}; - - -/** - * @file audiortp.h - * @brief Manage the real-time data transport in a SIP call - */ - - -class SIPCall; - -/////////////////////////////////////////////////////////////////////////////// -// Two pair of sockets -/////////////////////////////////////////////////////////////////////////////// -class AudioRtpRTX : public ost::Thread, public ost::TimerPort { - public: - /** - * Constructor - * @param sipcall The pointer on the SIP call - * @param sym Tells whether or not the voip links are symmetric - */ - AudioRtpRTX (SIPCall* sipcall, bool sym); - - /** - * Destructor - */ - ~AudioRtpRTX(); - - /** For incoming call notification */ - ost::Time *time; - - /** Thread associated method */ - virtual void run (); - - /** A SIP call */ - SIPCall* _ca; - - /** - * Update RTP session media info as received from SDP negociation - */ - void setRtpSessionMedia(void); - - /** - * Update RTP session remote ip destination as received from sip transaction - */ - void setRtpSessionRemoteIp(void); - - - friend class RtpTest; - - private: - - // copy constructor - AudioRtpRTX(const AudioRtpRTX& rh); - - // assignment operator - AudioRtpRTX& operator=(const AudioRtpRTX& rh); - - /** RTP session to send data */ - ost::RTPSession *_sessionSend; - - /** RTP session to receive data */ - ost::RTPSession *_sessionRecv; - - /** RTP symmetric session ( receive and send data in the same session ) */ - ost::SymmetricRTPSession *_session; - - /** Semaphore */ - // ost::Semaphore _start; - - /** Is the session symmetric or not */ - bool _sym; - - /** Mic-data related buffers */ - SFLDataFormat* micData; - SFLDataFormat* micDataConverted; - unsigned char* micDataEncoded; - - /** Speaker-data related buffers */ - SFLDataFormat* spkrDataDecoded; - SFLDataFormat* spkrDataConverted; - - /** Sample rate converter object */ - SamplerateConverter* converter; - - /** audio layer */ - AudioLayer *_audiolayer; - - /** Variables to process audio stream: sample rate for playing sound (typically 44100HZ) */ - int _layerSampleRate; - - /** Sample rate of the codec we use to encode and decode (most of time 8000HZ) */ - int _codecSampleRate; - - /** Length of the sound frame we capture in ms (typically 20ms) */ - int _layerFrameSize; - - /** Codecs frame size in samples (20 ms => 882 at 44.1kHz) - The exact value is stored in the codec */ - int _codecFrameSize; - - /** Speaker buffer length in samples once the data are resampled - * (used for mixing and recording) - */ - int _nSamplesSpkr; - - /** Mic buffer length in samples once the data are resampled - * (used for mixing and recording) - */ - int _nSamplesMic; - - /** - * Maximum number of sample for audio buffers (mic and spkr) - */ - int nbSamplesMax; - - - - bool _payloadIsSet; - bool _remoteIpIsSet; - - /** - * Init the RTP session. Create either symmetric or double sessions to manage data transport - * Set the payloads according to the manager preferences - */ - void initAudioRtpSession(void); - - /** - * Return the lenth the codec frame in ms - */ - float computeCodecFrameSize(int codecSamplePerFrame, int codecClockRate); - - /** - * Compute nb of byte to get coresponding to X ms at audio layer frame size (44.1 khz) - */ - int computeNbByteAudioLayer(float codecFrameSize); - - - int processDataEncode(); - - - void processDataDecode(unsigned char* spkrData, unsigned int size, int& countTime); - - - /** - * Get the data from the mic, encode it and send it through the RTP session - * @param timestamp To manage time and synchronizing - */ - void sendSessionFromMic(int timestamp); - - /** - * Get the data from the RTP packets, decode it and send it to the sound card - * @param countTime To manage time and synchronizing - */ - void receiveSessionForSpkr(int& countTime); - - /** - * Init the buffers used for processing sound data - */ - void initBuffers(void); - - /** - * Call the appropriate function, up or downsampling - * @param sampleRate_codec The sample rate of the codec selected to encode/decode the data - * @param nbSamples Number of samples to process - * @param status Type of resampling - * UPSAMPLING - * DOWNSAMPLING - * @return int The number of samples after process - */ - int reSampleData(SFLDataFormat *input, SFLDataFormat *output,int sampleRate_codec, int nbSamples, int status); - - /** The audio codec used during the session */ - AudioCodec *_audiocodec; - // AudioCodec _audioCodecInstance; - - /** Mutex */ - ost::Mutex _rtpRtxMutex; - - public: - - std::fstream *rtp_input_rec; - std::fstream *rtp_output_rec; - - static int count_rtp; - - -}; - -/////////////////////////////////////////////////////////////////////////////// -// Main class rtp -/////////////////////////////////////////////////////////////////////////////// -class AudioRtp { - public: - /** - * Constructor - */ - AudioRtp(); - - /** - * Destructor - */ - ~AudioRtp(); - - /** - * Create a brand new RTP session by calling the AudioRtpRTX constructor - * @param ca A pointer on a SIP call - */ - void createNewSession (SIPCall *ca); - - /** - * Start the AudioRtpRTX thread created with createNewSession - */ - int start(void); - - /** - * Close a RTP session and kills the remaining threads - */ - bool closeRtpSession( void ); - - /** - * Start recording - */ - // void setRecording (); - - friend class RtpTest; - - /** - * - */ - inline AudioRtpRTX * getAudioRtpRtxThread(void) { return _RTXThread; } - private: - // copy constructor - AudioRtp(const AudioRtp& rh); - - // assignment operator - AudioRtp& operator=(const AudioRtp& rh); - - /** The RTP thread */ - AudioRtpRTX* _RTXThread; - - /** Symmetric session or not */ - bool _symmetric; - - /** Mutex */ - ost::Mutex _rtpMutex; - -}; - -#endif // __AUDIO_RTP_H__ diff --git a/sflphone-common/src/audio/audiortp/AudioRtpFactory.cpp b/sflphone-common/src/audio/audiortp/AudioRtpFactory.cpp index cb3480979ef3ec910d2cbc07588b68dc96966410..09756c4adff42163459b71e15d7f3cec7fc80c21 100644 --- a/sflphone-common/src/audio/audiortp/AudioRtpFactory.cpp +++ b/sflphone-common/src/audio/audiortp/AudioRtpFactory.cpp @@ -22,7 +22,6 @@ #include "AudioZrtpSession.h" #include "AudioSrtpSession.h" #include "AudioSymmetricRtpSession.h" - #include "manager.h" #include "account.h" #include "sip/sipcall.h" @@ -122,7 +121,7 @@ void AudioRtpFactory::initAudioRtpSession (SIPCall * ca) } } -void AudioRtpFactory::start (void) +void AudioRtpFactory::start (AudioCodec* audiocodec) { if (_rtpSession == NULL) { throw AudioRtpFactoryException ("RTP: Error: _rtpSession was null when trying to start audio thread"); @@ -131,7 +130,7 @@ void AudioRtpFactory::start (void) switch (_rtpSessionType) { case Sdes: - if (static_cast<AudioSrtpSession *> (_rtpSession)->startRtpThread() != 0) { + if (static_cast<AudioSrtpSession *> (_rtpSession)->startRtpThread(audiocodec) != 0) { throw AudioRtpFactoryException ("RTP: Error: Failed to start AudioSRtpSession thread"); } break; @@ -139,7 +138,7 @@ void AudioRtpFactory::start (void) case Symmetric: _debug ("Starting symmetric rtp thread"); - if (static_cast<AudioSymmetricRtpSession *> (_rtpSession)->startRtpThread() != 0) { + if (static_cast<AudioSymmetricRtpSession *> (_rtpSession)->startRtpThread(audiocodec) != 0) { throw AudioRtpFactoryException ("RTP: Error: Failed to start AudioSymmetricRtpSession thread"); } @@ -147,7 +146,7 @@ void AudioRtpFactory::start (void) case Zrtp: - if (static_cast<AudioZrtpSession *> (_rtpSession)->startRtpThread() != 0) { + if (static_cast<AudioZrtpSession *> (_rtpSession)->startRtpThread(audiocodec) != 0) { throw AudioRtpFactoryException ("RTP: Error: Failed to start AudioZrtpSession thread"); } break; @@ -210,6 +209,15 @@ void AudioRtpFactory::updateDestinationIpAddress (void) } } +sfl::AudioSymmetricRtpSession * AudioRtpFactory::getAudioSymetricRtpSession() +{ + if ( (_rtpSessionType == Symmetric) && (_rtpSessionType != NULL)) { + return static_cast<AudioSymmetricRtpSession *> (_rtpSession); + } else { + throw AudioRtpFactoryException("RTP: Error: _rtpSession is NULL in getAudioSymetricRtpSession"); + } +} + sfl::AudioZrtpSession * AudioRtpFactory::getAudioZrtpSession() { if ( (_rtpSessionType == Zrtp) && (_rtpSessionType != NULL)) { diff --git a/sflphone-common/src/audio/audiortp/AudioRtpFactory.h b/sflphone-common/src/audio/audiortp/AudioRtpFactory.h index a1c93d2cdcfe9b78186188d45cbe442d2fc8879b..de16a31fe610b5ae2e27420f451d47bb87d0b7a9 100644 --- a/sflphone-common/src/audio/audiortp/AudioRtpFactory.h +++ b/sflphone-common/src/audio/audiortp/AudioRtpFactory.h @@ -23,6 +23,7 @@ #include <cc++/thread.h> #include "sip/SdesNegotiator.h" +#include "audio/codecs/audiocodec.h" class SdesNegotiator; class SIPCall; @@ -30,6 +31,7 @@ class SIPCall; namespace sfl { class AudioZrtpSession; class AudioSrtpSession; + class AudioSymmetricRtpSession; } namespace sfl { @@ -76,7 +78,7 @@ namespace sfl { * file. initAudioRtpSession must have been called prior to that. * @param None */ - void start(); + void start(AudioCodec*); /** * Stop the audio rtp thread of the type specified in the configuration @@ -98,6 +100,8 @@ namespace sfl { */ inline void * getAudioRtpSession(void) { return _rtpSession; } + AudioSymmetricRtpSession * getAudioSymetricRtpSession(); + /** * @param None * @return The internal audio rtp session type diff --git a/sflphone-common/src/audio/audiortp/AudioRtpSession.h b/sflphone-common/src/audio/audiortp/AudioRtpSession.h index cb0578beaa7a12d70b5efd781fd3fd29b07afcdb..9213eefad2698f2a266d60b27e54a6f0c187a86c 100644 --- a/sflphone-common/src/audio/audiortp/AudioRtpSession.h +++ b/sflphone-common/src/audio/audiortp/AudioRtpSession.h @@ -75,7 +75,7 @@ namespace sfl { // Thread associated method virtual void run (); - int startRtpThread(); + int startRtpThread(AudioCodec*); /** * Used mostly when receiving a reinvite @@ -92,23 +92,24 @@ namespace sfl { */ void sendDtmfEvent(sfl::DtmfEvent *dtmf); + inline float computeCodecFrameSize (int codecSamplePerFrame, int codecClockRate) { + return ( (float) codecSamplePerFrame * 1000.0) / (float) codecClockRate; + } + + int computeNbByteAudioLayer (float codecFrameSize) { + return (int) ( ((float) _converterSamplingRate * codecFrameSize * sizeof(SFLDataFormat))/ 1000.0); + } + private: void initBuffers(void); void setSessionTimeouts(void); - void setSessionMedia(void); + void setSessionMedia(AudioCodec*); void setDestinationIpAddress(void); int processDataEncode(void); void processDataDecode(unsigned char * spkrData, unsigned int size); - - inline float computeCodecFrameSize (int codecSamplePerFrame, int codecClockRate) { - return ( (float) codecSamplePerFrame * 1000.0) / (float) codecClockRate; - } - int computeNbByteAudioLayer (float codecFrameSize) { - return (int) ( ((float) _converterSamplingRate * codecFrameSize * sizeof(SFLDataFormat))/ 1000.0); - } void sendMicData(); void receiveSpeakerData (); @@ -206,7 +207,6 @@ namespace sfl { protected: SIPCall * _ca; - }; template <typename D> @@ -307,17 +307,9 @@ namespace sfl { } template <typename D> - void AudioRtpSession<D>::setSessionMedia(void) + void AudioRtpSession<D>::setSessionMedia(AudioCodec* audiocodec) { - assert(_ca); - - AudioCodecType pl = (AudioCodecType)_ca->getLocalSDP()->get_session_media()->getPayload(); - _audiocodec = _manager->getCodecDescriptorMap().instantiateCodec(pl); - - if (_audiocodec == NULL) { - _debug ("No audiocodec, can't init RTP media"); - throw AudioRtpSessionException(); - } + _audiocodec = audiocodec; _debug ("Init audio RTP session: codec payload %i", _audiocodec->getPayload()); @@ -617,23 +609,20 @@ namespace sfl { } template <typename D> - int AudioRtpSession<D>::startRtpThread () + int AudioRtpSession<D>::startRtpThread (AudioCodec* audiocodec) { _debug("Starting main thread"); + setSessionTimeouts(); + setSessionMedia(audiocodec); + initBuffers(); return start(_mainloopSemaphore); } template <typename D> void AudioRtpSession<D>::run () { - - setSessionTimeouts(); - setSessionMedia(); - - initBuffers(); - - // Timestamp must be initialized randomly - _timestamp = static_cast<D*>(this)->getCurrentTimestamp(); + // Timestamp must be initialized randomly + _timestamp = static_cast<D*>(this)->getCurrentTimestamp(); int sessionWaiting; int threadSleep = 0; diff --git a/sflphone-common/src/sip/sipvoiplink.cpp b/sflphone-common/src/sip/sipvoiplink.cpp index 022cdcbe0c2dd16cc5b97e6115570756b9cb7bd6..4d1e25a850a9f7fef5de7f0bf1aaed5395927bd3 100644 --- a/sflphone-common/src/sip/sipvoiplink.cpp +++ b/sflphone-common/src/sip/sipvoiplink.cpp @@ -3299,10 +3299,19 @@ void call_on_media_update (pjsip_inv_session *inv, pj_status_t status) _debug("Sdes not initialized for this call\n"); } + assert(call->getLocalSDP()); + assert(call->getLocalSDP()->get_session_media()); + + AudioCodecType pl = (AudioCodecType)call->getLocalSDP()->get_session_media()->getPayload(); + AudioCodec* audiocodec = Manager::instance().getCodecDescriptorMap().instantiateCodec(pl); + + if (audiocodec == NULL) + _error ("SIP: No audiocodec found"); + try { call->setAudioStart (true); - call->getAudioRtp()->start(); + call->getAudioRtp()->start(audiocodec); } catch (exception& rtpException) { _debug ("%s", rtpException.what()); }