Skip to content
Snippets Groups Projects
Commit ae0538ad authored by Julien Bonjean's avatar Julien Bonjean
Browse files

[#2535] Refactoring (for unit tests)

parent 5be88657
Branches
Tags
No related merge requests found
/*
* 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
/*
* 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__
...@@ -22,7 +22,6 @@ ...@@ -22,7 +22,6 @@
#include "AudioZrtpSession.h" #include "AudioZrtpSession.h"
#include "AudioSrtpSession.h" #include "AudioSrtpSession.h"
#include "AudioSymmetricRtpSession.h" #include "AudioSymmetricRtpSession.h"
#include "manager.h" #include "manager.h"
#include "account.h" #include "account.h"
#include "sip/sipcall.h" #include "sip/sipcall.h"
...@@ -122,7 +121,7 @@ void AudioRtpFactory::initAudioRtpSession (SIPCall * ca) ...@@ -122,7 +121,7 @@ void AudioRtpFactory::initAudioRtpSession (SIPCall * ca)
} }
} }
void AudioRtpFactory::start (void) void AudioRtpFactory::start (AudioCodec* audiocodec)
{ {
if (_rtpSession == NULL) { if (_rtpSession == NULL) {
throw AudioRtpFactoryException ("RTP: Error: _rtpSession was null when trying to start audio thread"); throw AudioRtpFactoryException ("RTP: Error: _rtpSession was null when trying to start audio thread");
...@@ -131,7 +130,7 @@ void AudioRtpFactory::start (void) ...@@ -131,7 +130,7 @@ void AudioRtpFactory::start (void)
switch (_rtpSessionType) { switch (_rtpSessionType) {
case Sdes: 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"); throw AudioRtpFactoryException ("RTP: Error: Failed to start AudioSRtpSession thread");
} }
break; break;
...@@ -139,7 +138,7 @@ void AudioRtpFactory::start (void) ...@@ -139,7 +138,7 @@ void AudioRtpFactory::start (void)
case Symmetric: case Symmetric:
_debug ("Starting symmetric rtp thread"); _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"); throw AudioRtpFactoryException ("RTP: Error: Failed to start AudioSymmetricRtpSession thread");
} }
...@@ -147,7 +146,7 @@ void AudioRtpFactory::start (void) ...@@ -147,7 +146,7 @@ void AudioRtpFactory::start (void)
case Zrtp: 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"); throw AudioRtpFactoryException ("RTP: Error: Failed to start AudioZrtpSession thread");
} }
break; break;
...@@ -210,6 +209,15 @@ void AudioRtpFactory::updateDestinationIpAddress (void) ...@@ -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() sfl::AudioZrtpSession * AudioRtpFactory::getAudioZrtpSession()
{ {
if ( (_rtpSessionType == Zrtp) && (_rtpSessionType != NULL)) { if ( (_rtpSessionType == Zrtp) && (_rtpSessionType != NULL)) {
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include <cc++/thread.h> #include <cc++/thread.h>
#include "sip/SdesNegotiator.h" #include "sip/SdesNegotiator.h"
#include "audio/codecs/audiocodec.h"
class SdesNegotiator; class SdesNegotiator;
class SIPCall; class SIPCall;
...@@ -30,6 +31,7 @@ class SIPCall; ...@@ -30,6 +31,7 @@ class SIPCall;
namespace sfl { namespace sfl {
class AudioZrtpSession; class AudioZrtpSession;
class AudioSrtpSession; class AudioSrtpSession;
class AudioSymmetricRtpSession;
} }
namespace sfl { namespace sfl {
...@@ -76,7 +78,7 @@ namespace sfl { ...@@ -76,7 +78,7 @@ namespace sfl {
* file. initAudioRtpSession must have been called prior to that. * file. initAudioRtpSession must have been called prior to that.
* @param None * @param None
*/ */
void start(); void start(AudioCodec*);
/** /**
* Stop the audio rtp thread of the type specified in the configuration * Stop the audio rtp thread of the type specified in the configuration
...@@ -98,6 +100,8 @@ namespace sfl { ...@@ -98,6 +100,8 @@ namespace sfl {
*/ */
inline void * getAudioRtpSession(void) { return _rtpSession; } inline void * getAudioRtpSession(void) { return _rtpSession; }
AudioSymmetricRtpSession * getAudioSymetricRtpSession();
/** /**
* @param None * @param None
* @return The internal audio rtp session type * @return The internal audio rtp session type
......
...@@ -75,7 +75,7 @@ namespace sfl { ...@@ -75,7 +75,7 @@ namespace sfl {
// Thread associated method // Thread associated method
virtual void run (); virtual void run ();
int startRtpThread(); int startRtpThread(AudioCodec*);
/** /**
* Used mostly when receiving a reinvite * Used mostly when receiving a reinvite
...@@ -92,24 +92,25 @@ namespace sfl { ...@@ -92,24 +92,25 @@ namespace sfl {
*/ */
void sendDtmfEvent(sfl::DtmfEvent *dtmf); 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: private:
void initBuffers(void); void initBuffers(void);
void setSessionTimeouts(void); void setSessionTimeouts(void);
void setSessionMedia(void); void setSessionMedia(AudioCodec*);
void setDestinationIpAddress(void); void setDestinationIpAddress(void);
int processDataEncode(void); int processDataEncode(void);
void processDataDecode(unsigned char * spkrData, unsigned int size); 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 sendMicData();
void receiveSpeakerData (); void receiveSpeakerData ();
...@@ -206,7 +207,6 @@ namespace sfl { ...@@ -206,7 +207,6 @@ namespace sfl {
protected: protected:
SIPCall * _ca; SIPCall * _ca;
}; };
template <typename D> template <typename D>
...@@ -307,17 +307,9 @@ namespace sfl { ...@@ -307,17 +307,9 @@ namespace sfl {
} }
template <typename D> template <typename D>
void AudioRtpSession<D>::setSessionMedia(void) void AudioRtpSession<D>::setSessionMedia(AudioCodec* audiocodec)
{ {
assert(_ca); _audiocodec = audiocodec;
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();
}
_debug ("Init audio RTP session: codec payload %i", _audiocodec->getPayload()); _debug ("Init audio RTP session: codec payload %i", _audiocodec->getPayload());
...@@ -617,21 +609,18 @@ namespace sfl { ...@@ -617,21 +609,18 @@ namespace sfl {
} }
template <typename D> template <typename D>
int AudioRtpSession<D>::startRtpThread () int AudioRtpSession<D>::startRtpThread (AudioCodec* audiocodec)
{ {
_debug("Starting main thread"); _debug("Starting main thread");
setSessionTimeouts();
setSessionMedia(audiocodec);
initBuffers();
return start(_mainloopSemaphore); return start(_mainloopSemaphore);
} }
template <typename D> template <typename D>
void AudioRtpSession<D>::run () void AudioRtpSession<D>::run ()
{ {
setSessionTimeouts();
setSessionMedia();
initBuffers();
// Timestamp must be initialized randomly // Timestamp must be initialized randomly
_timestamp = static_cast<D*>(this)->getCurrentTimestamp(); _timestamp = static_cast<D*>(this)->getCurrentTimestamp();
......
...@@ -3299,10 +3299,19 @@ void call_on_media_update (pjsip_inv_session *inv, pj_status_t status) ...@@ -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"); _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 { try {
call->setAudioStart (true); call->setAudioStart (true);
call->getAudioRtp()->start(); call->getAudioRtp()->start(audiocodec);
} catch (exception& rtpException) { } catch (exception& rtpException) {
_debug ("%s", rtpException.what()); _debug ("%s", rtpException.what());
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment