diff --git a/sflphone-common/src/audio/audiortp/AudioRtpFactory.cpp b/sflphone-common/src/audio/audiortp/AudioRtpFactory.cpp
index 41f572972ad7f06aa09f9aeacb2d7ca50bdc0948..d4e649ca77b6c137ef5a5f2674bf0ee0fbb9535b 100644
--- a/sflphone-common/src/audio/audiortp/AudioRtpFactory.cpp
+++ b/sflphone-common/src/audio/audiortp/AudioRtpFactory.cpp
@@ -1,6 +1,7 @@
 /*
  *  Copyright (C) 2004, 2005, 2006, 2009, 2008, 2009, 2010 Savoir-Faire Linux Inc.
  *  Author: Pierre-Luc Bacon <pierre-luc.bacon@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
diff --git a/sflphone-common/src/audio/audiortp/AudioRtpFactory.h b/sflphone-common/src/audio/audiortp/AudioRtpFactory.h
index b5183d67b2a509957423d08a41549e6af32ae672..a88cfe2a3a128637b56a36d22535f854f4ed68c1 100644
--- a/sflphone-common/src/audio/audiortp/AudioRtpFactory.h
+++ b/sflphone-common/src/audio/audiortp/AudioRtpFactory.h
@@ -1,6 +1,7 @@
 /*
  *  Copyright (C) 2004, 2005, 2006, 2009, 2008, 2009, 2010 Savoir-Faire Linux Inc.
  *  Author: Pierre-Luc Bacon <pierre-luc.bacon@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
diff --git a/sflphone-common/src/audio/audiortp/AudioRtpRecordHandler.cpp b/sflphone-common/src/audio/audiortp/AudioRtpRecordHandler.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..d783b894e0f7f9850635c3454ad688ec896a7516
--- /dev/null
+++ b/sflphone-common/src/audio/audiortp/AudioRtpRecordHandler.cpp
@@ -0,0 +1,437 @@
+/*
+ *  Copyright (C) 2004, 2005, 2006, 2009, 2008, 2009, 2010 Savoir-Faire Linux Inc.
+ *  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.
+ *
+ *  Additional permission under GNU GPL version 3 section 7:
+ *
+ *  If you modify this program, or any covered work, by linking or
+ *  combining it with the OpenSSL project's OpenSSL library (or a
+ *  modified version of that library), containing parts covered by the
+ *  terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc.
+ *  grants you additional permission to convey the resulting work.
+ *  Corresponding Source for a non-source form of such a combination
+ *  shall include the source code for the parts of OpenSSL used as well
+ *  as that of the covered work.
+ */
+
+#include "AudioRtpRecordHandler.h"
+
+namespace sfl
+{
+
+static const SFLDataFormat initFadeinFactor = 32000;
+
+AudioRtpRecord::AudioRtpRecord() : _audioCodec(NULL)
+								 , _hasDynamicPayloadType(false)
+								 , _micData(NULL)
+								 , _micDataConverted(NULL)
+								 , _micDataEncoded(NULL)
+								 , _spkrDataDecoded(NULL)
+								 , _spkrDataConverted(NULL)
+								 , _converter(NULL)
+								 , _audioLayerSampleRate(0)
+								 , _codecSampleRate(0)
+								 , _audioLayerFrameSize(0)
+								 , _codecFrameSize(0)
+								 , _converterSamplingRate(0)
+								 , _micFadeInComplete(false)
+								 , _spkrFadeInComplete(false)
+								 , _micAmplFactor(initFadeinFactor)
+								 , _spkrAmplFactor(initFadeinFactor)
+								 , _audioProcess(NULL)
+								 , _noiseSuppress(NULL)
+{
+	_audioLayerFrameSize = _manager->getAudioDriver()->getFrameSize(); // in ms
+	_audioLayerSampleRate = _manager->getAudioDriver()->getSampleRate();
+}
+
+
+AudioRtpRecord::~AudioRtpRecord()
+{
+	if (_micData)
+		delete [] _micData;
+	_micData = NULL;
+
+	if (_micDataConverted)
+		delete [] _micDataConverted;
+	_micDataConverted = NULL;
+
+	if (_micDataEncoded)
+		delete [] _micDataEncoded;
+	_micDataEncoded = NULL;
+
+	if (_spkrDataDecoded)
+		delete [] _spkrDataDecoded;
+	_spkrDataDecoded = NULL;
+
+	if (_spkrDataConverted)
+		delete [] _spkrDataConverted;
+	_spkrDataConverted = NULL;
+
+
+	if(_converter)
+		delete _converter;
+	_converter = NULL;
+
+	if (_audioCodec) {
+		delete _audioCodec;
+		_audioCodec = NULL;
+	}
+
+	if (_audioProcess) {
+		delete _audioProcess;
+		_audioProcess = NULL;
+	}
+
+	if (_noiseSuppress) {
+		delete _noiseSuppress;
+		_noiseSuppress = NULL;
+	}
+}
+
+AudioCodec *AudioRtpRecord::getAudiocodec() const
+{
+    return _audioCodec;
+}
+
+int AudioRtpRecord::getCodecPayloadType() const
+{
+    return _codecPayloadType;
+}
+
+bool AudioRtpRecord::getHasDynamicPayload() const
+{
+	return _hasDynamicPayloadType;
+}
+
+int AudioRtpRecord::getAudioLayerFrameSize() const
+{
+    return _audioLayerFrameSize;
+}
+
+int AudioRtpRecord::getAudioLayerSampleRate() const
+{
+    return _audioLayerSampleRate;
+}
+
+int AudioRtpRecord::getCodecFrameSize() const
+{
+    return _codecFrameSize;
+}
+
+int AudioRtpRecord::getCodecSampleRate() const
+{
+    return _codecSampleRate;
+}
+
+SamplerateConverter *AudioRtpRecord::getConverter() const
+{
+    return _converter;
+}
+
+int AudioRtpRecord::getConverterSamplingRate() const
+{
+    return _converterSamplingRate;
+}
+
+EventQueue *AudioRtpRecord::getEventQueue() const
+{
+    return &_eventQueue;
+}
+
+int AudioRtpRecord::getEventQueueSize() const
+{
+	return _eventQueue.size();
+}
+
+unsigned char *getEncodedData() const
+{
+	return _micDataEncoded;
+}
+
+void AudioRtpRecord::setAudiocodec(AudioCodec *audiocodec)
+{
+    this->_audiocodec = audiocodec;
+}
+
+void AudioRtpRecord::setCodecPayloadType(int codecPayloadType)
+{
+    this->codecPayloadType = codecPayloadType;
+}
+
+bool AudioRtpRecord::setHasDynamicPayload(bool hasDynamicPayload)
+{
+	_hasDynamicPayloadType = hasDynamicPayload;
+}
+
+void AudioRtpRecord::setAudioLayerFrameSize(int _audioLayerFrameSize)
+{
+    this->_audioLayerFrameSize = _audioLayerFrameSize;
+}
+
+void AudioRtpRecord::setAudioLayerSampleRate(int _audioLayerSampleRate)
+{
+    this->_audioLayerSampleRate = _audioLayerSampleRate;
+}
+
+void AudioRtpRecord::setCodecFrameSize(int _codecFrameSize)
+{
+    this->_codecFrameSize = _codecFrameSize;
+}
+
+void AudioRtpRecord::setCodecSampleRate(int _codecSampleRate)
+{
+    this->_codecSampleRate = _codecSampleRate;
+}
+
+void AudioRtpRecord::setConverter(SamplerateConverter *_converter)
+{
+    this->_converter = _converter;
+}
+
+void AudioRtpRecord::setConverterSamplingRate(int _converterSamplingRate)
+{
+    this->_converterSamplingRate = _converterSamplingRate;
+}
+
+void AudioRtpRecord::setEventQueue(EventQueue _eventQueue)
+{
+    this->_eventQueue = _eventQueue;
+}
+
+
+AudioRtpRecordHandler::AudioRtpRecordHandler() {
+	// TODO Auto-generated constructor stub
+
+}
+
+
+AudioRtpRecordHandler::~AudioRtpRecordHandler() {
+	// TODO Auto-generated destructor stub
+}
+
+void AudioRtpRecord::SetRtpMedia(AudioCodec* audioCodec) {
+
+	// Set varios codec info to reduce indirection
+	_audioRtpRecord.setAudioCodec(audioCodec);
+	_audioRtpRecord.setCodecPayloadType(audioCodec->getPayloadType());
+    _audioRtpRecord.setCodecSampleRate(audioCodec->getClockRate());
+    _audioRtpRecord.setCodecFrameSize(audioCodec->getFrameSize());
+    _audioRtpRecord.setHasDynamicPayload(audioCodec->hasDynamicPayload());
+}
+
+
+void AudioRtpRecord::init()
+{
+    // init noise reduction process
+    // _noiseSuppress = new NoiseSuppress (getCodecFrameSize(), getCodecSampleRate());
+    // _audioProcess = new AudioProcessing (_noiseSuppress);
+
+	// _audioRtpRecord._noiseSuppress
+	// _audioRtpRecord.
+}
+
+void AudioRtpRecord::initBuffers()
+{
+    // Set sampling rate, main buffer choose the highest one
+    _manager->getAudioDriver()->getMainBuffer()->setInternalSamplingRate (_codecSampleRate);
+
+    // may be different than one already set
+    _converterSamplingRate = _manager->getAudioDriver()->getMainBuffer()->getInternalSamplingRate();
+
+    // initialize SampleRate converter using AudioLayer's sampling rate
+    // (internal buffers initialized with maximal sampling rate and frame size)
+    _converter = new SamplerateConverter (_layerSampleRate, _layerFrameSize);
+
+    int nbSamplesMax = (int) (_codecSampleRate * _layerFrameSize /1000) *2;
+    _micData = new SFLDataFormat[nbSamplesMax];
+    _micDataConverted = new SFLDataFormat[nbSamplesMax];
+    _micDataEncoded = new unsigned char[nbSamplesMax*2];
+    _spkrDataConverted = new SFLDataFormat[nbSamplesMax];
+    _spkrDataDecoded = new SFLDataFormat[nbSamplesMax];
+
+
+    memset (_micData, 0, nbSamplesMax*sizeof (SFLDataFormat));
+    memset (_micDataConverted, 0, nbSamplesMax*sizeof (SFLDataFormat));
+    memset (_micDataEncoded, 0, nbSamplesMax*2);
+    memset (_spkrDataConverted, 0, nbSamplesMax*sizeof (SFLDataFormat));
+    memset (_spkrDataDecoded, 0, nbSamplesMax*sizeof (SFLDataFormat));
+
+    _manager->addStream (_ca->getCallId());
+}
+
+
+void AudioRtpRecordHandler::putDtmfEvent (int digit)
+{
+
+    sfl::DtmfEvent *dtmf = new sfl::DtmfEvent();
+
+    dtmf->payload.event = digit;
+    dtmf->payload.ebit = false; 			// end of event bit
+    dtmf->payload.rbit = false;  		// reserved bit
+    dtmf->payload.duration = 1; 	        // duration for this event
+    dtmf->newevent = true;
+    dtmf->length = 1000;
+
+    _eventQueue.push_back (dtmf);
+
+    _debug ("AudioRtpSession: Put Dtmf Event %d", _eventQueue.size());
+}
+
+int AudioRtpRecordHandler::processDataEncode (void)
+{
+    assert (_audiocodec);
+    assert (_audiolayer);
+
+    int _mainBufferSampleRate = _manager->getAudioDriver()->getMainBuffer()->getInternalSamplingRate();
+
+    // 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 = _manager->getAudioDriver()->getMainBuffer()->availForGet (_ca->getCallId());
+
+    // set available byte to maxByteToGet
+    int bytesAvail = (availBytesFromMic < maxBytesToGet) ? availBytesFromMic : maxBytesToGet;
+
+    if (bytesAvail == 0) {
+        memset (_micDataEncoded, 0, sizeof (SFLDataFormat));
+        return _audiocodec->getFrameSize();
+    }
+
+    // Get bytes from micRingBuffer to data_from_mic
+    int nbSample = _manager->getAudioDriver()->getMainBuffer()->getData (_micData , bytesAvail, 100, _ca->getCallId()) / sizeof (SFLDataFormat);
+
+    if (!_micFadeInComplete)
+        _micFadeInComplete = fadeIn (_micData, nbSample, &_micAmplFactor);
+
+    if (nbSample == 0)
+        return nbSample;
+
+    // nb bytes to be sent over RTP
+    int compSize = 0;
+
+    // test if resampling is required
+    if (_audiocodec->getClockRate() != _mainBufferSampleRate) {
+        int nb_sample_up = nbSample;
+
+        _nSamplesMic = nbSample;
+
+        nbSample = _converter->downsampleData (_micData , _micDataConverted , _audiocodec->getClockRate(), _mainBufferSampleRate, nb_sample_up);
+
+        if (_manager->audioPreference.getNoiseReduce())
+            _audioProcess->processAudio (_micDataConverted, nbSample*sizeof (SFLDataFormat));
+
+        compSize = _audiocodec->codecEncode (_micDataEncoded, _micDataConverted, nbSample*sizeof (SFLDataFormat));
+
+    } else {
+
+        _nSamplesMic = nbSample;
+
+        if (_manager->audioPreference.getNoiseReduce())
+            _audioProcess->processAudio (_micData, nbSample*sizeof (SFLDataFormat));
+
+        // no resampling required
+        compSize = _audiocodec->codecEncode (_micDataEncoded, _micData, nbSample*sizeof (SFLDataFormat));
+
+    }
+
+    return compSize;
+}
+
+void AudioRtpRecordHandler::processDataDecode (unsigned char * spkrData, unsigned int size)
+{
+    if (_audiocodec != NULL) {
+
+
+        int _mainBufferSampleRate = _manager->getAudioDriver()->getMainBuffer()->getInternalSamplingRate();
+
+        // 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);
+
+        if (!_spkrFadeInComplete)
+            _spkrFadeInComplete = fadeIn (_spkrDataDecoded, nbSample, &_spkrAmplFactor);
+
+        // test if resampling is required
+        if (_audiocodec->getClockRate() != _mainBufferSampleRate) {
+
+            // Do sample rate conversion
+            int nb_sample_down = nbSample;
+
+            nbSample = _converter->upsampleData (_spkrDataDecoded, _spkrDataConverted, _codecSampleRate, _mainBufferSampleRate, nb_sample_down);
+
+            // Store the number of samples for recording
+            _nSamplesSpkr = nbSample;
+
+            // put data in audio layer, size in byte
+            _manager->getAudioDriver()->getMainBuffer()->putData (_spkrDataConverted, nbSample * sizeof (SFLDataFormat), 100, _ca->getCallId());
+
+
+        } else {
+            // Store the number of samples for recording
+            _nSamplesSpkr = nbSample;
+
+            // put data in audio layer, size in byte
+            _manager->getAudioDriver()->getMainBuffer()->putData (_spkrDataDecoded, expandedSize, 100, _ca->getCallId());
+        }
+
+        // Notify (with a beep) an incoming call when there is already a call
+        if (_manager->incomingCallWaiting() > 0) {
+            _countNotificationTime += _time->getSecond();
+            int countTimeModulo = _countNotificationTime % 5000;
+
+            // _debug("countNotificationTime: %d\n", countNotificationTime);
+            // _debug("countTimeModulo: %d\n", countTimeModulo);
+            if ( (countTimeModulo - _countNotificationTime) < 0) {
+                _manager->notificationIncomingCall();
+            }
+
+            _countNotificationTime = countTimeModulo;
+        }
+
+    }
+}
+
+
+bool AudioRtpRecordHandler::fadeIn (SFLDataFormat *audio, int size, SFLDataFormat *factor)
+{
+
+    // apply amplitude factor;
+    while (size) {
+        size--;
+        audio[size] /= *factor;
+    }
+
+    // decrease factor
+    *factor /= FADEIN_STEP_SIZE;
+
+    // if factor reach 0, thsi function should no be called anymore
+    if (*factor == 0)
+        return true;
+
+    return false;
+}
+
+
+
+}
+
diff --git a/sflphone-common/src/audio/audiortp/AudioRtpRecordHandler.h b/sflphone-common/src/audio/audiortp/AudioRtpRecordHandler.h
new file mode 100644
index 0000000000000000000000000000000000000000..76d63ccce3cd99a76131eb60ce5099005c64e85d
--- /dev/null
+++ b/sflphone-common/src/audio/audiortp/AudioRtpRecordHandler.h
@@ -0,0 +1,324 @@
+/*
+ *  Copyright (C) 2004, 2005, 2006, 2009, 2008, 2009, 2010 Savoir-Faire Linux Inc.
+ *  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.
+ *
+ *  Additional permission under GNU GPL version 3 section 7:
+ *
+ *  If you modify this program, or any covered work, by linking or
+ *  combining it with the OpenSSL project's OpenSSL library (or a
+ *  modified version of that library), containing parts covered by the
+ *  terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc.
+ *  grants you additional permission to convey the resulting work.
+ *  Corresponding Source for a non-source form of such a combination
+ *  shall include the source code for the parts of OpenSSL used as well
+ *  as that of the covered work.
+ */
+
+#ifndef AUDIORTPRECORDHANDLER_H_
+#define AUDIORTPRECORDHANDLER_H_
+
+#include "audio/codecs/audiocodec.h"
+#include "audio/samplerateconverter.h"
+#include "audio/audioprocessing.h"
+#include "audio/noisesuppress.h"
+
+namespace sfl
+{
+
+typedef struct DtmfEvent {
+    ost::RTPPacket::RFC2833Payload payload;
+    int length;
+    bool newevent;
+} DtmfEvent;
+
+typedef list<DtmfEvent *> EventQueue;
+
+/**
+ * Class meant to store internal data in order to encode/decode,
+ * resample, process, and packetize audio streams. This class should not be
+ * handled directly. Use AudioRtpRecorrdHandeler
+ */
+class AudioRtpRecord {
+public:
+	AudioRtpRecord();
+	virtual ~AudioRtpRecord();
+
+	/**
+	 * Return a pointer to the current codec instance
+	 */
+    inline AudioCodec *getAudioCodec() const;
+
+    /**
+     * Get current payload type (static or dynamic)
+     */
+    int getCodecPayloadType() const;
+
+    /**
+     * Return wether or not this codec has dynamic payload to be
+     * negotiated during SDP session
+     */
+    bool getHasDynamicPayload() const;
+
+    /**
+     * Get current audio layer frame size
+	 */
+    int getAudioLayerFrameSize() const;
+
+    /**
+     * Get current audio layer sampling rate
+     */
+    int getAudioLayerSampleRate() const;
+
+    /**
+     * Get current codec frame size
+     */
+    int getCodecFrameSize() const;
+
+    /**
+     * Return current sample rate
+     */
+    int getCodecSampleRate() const;
+
+    /**
+     * Get the sampling rate converter for this session
+     */
+    SamplerateConverter *getConverter() const;
+
+    /**
+     * Get sampling rate converter's sampling rate
+     */
+    inline int getConverterSamplingRate() const;
+
+    /**
+     * Return a poiner to the DTMF event queue
+     */
+    EventQueue *getEventQueue() const;
+
+    /**
+     * Return the number of DTMF event waiting in the queue
+     */
+    int getEventQueueSize() const;
+
+    unsigned char *getEncodedData() const;
+
+    /**
+     * Return a pointer to the current codec instance
+     */
+    void setAudioCodec(AudioCodec *audioCodec);
+
+    /**
+     * Set current codec payload (static or dynamic)
+     */
+    void setCodecPayloadType(int codecPayloadType);
+
+    /**
+     * Set audio layer frame size
+     */
+    void setAudioLayerFrameSize(int _audioLayerFrameSize);
+
+    /**
+     * Set current audio layer sampling rate
+     * used to process sampling rate conversion
+     */
+    void setAudioLayerSampleRate(int _audioLayerSampleRate);
+
+    /**
+     * Set codec frame size used to compute sampling rate conversion
+     */
+    void setCodecFrameSize(int _codecFrameSize);
+
+    /**
+     * Set codec sampling rate used to compute sampling rate conversion
+     */
+    void setCodecSampleRate(int _codecSampleRate);
+
+    /**
+     * Set sampling rate converter for this session
+     */
+    void setConverter(SamplerateConverter *_converter);
+
+    /**
+     * Set converter sampling rate used to compute conversion buffer size
+     */
+    void setConverterSamplingRate(int _converterSamplingRate);
+
+private:
+    /**
+     * Pointer to the session's codec
+	 */
+    AudioCodec * _audioCodec;
+
+    /**
+     * Codec payload type
+     */
+    int _codecPayloadType;
+
+    /**
+     * Dynamic payload are negotiated during sdp session while static payload
+     * are predefined numbers identifying the codec
+     */
+    bool _hasDynamicPayloadType;
+
+    /**
+     * 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;
+
+    /**
+     * Variables to process audio stream: sample rate for playing sound (typically 44100HZ)
+     */
+    int _audioLayerSampleRate;
+
+    /**
+     * 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 _audioLayerFrameSize;
+
+    /**
+     * Codecs frame size in samples (20 ms => 882 at 44.1kHz)
+     * The exact value is stored in the codec
+	 */
+    int _codecFrameSize;
+
+    /**
+     * Sampling rate of audio converter
+     */
+    int _converterSamplingRate;
+
+    /**
+     * EventQueue used to store list of DTMF-
+     */
+    EventQueue _eventQueue;
+
+    /**
+     * State of mic fade in
+     */
+    bool _micFadeInComplete;
+
+    /**
+       * State of spkr fade in
+     */
+    bool _spkrFadeInComplete;
+
+    /**
+     * Ampliturde factor to fade in mic data
+     */
+    SFLDataFormat _micAmplFactor;
+
+    /**
+     * Amplitude factor to fade in spkr data
+     */
+    SFLDataFormat _spkrAmplFactor;
+
+    /**
+     * Audio process containing noise reduction engine
+     */
+    AudioProcessing *_audioProcess;
+
+    /**
+     * Noise reduction engine
+     */
+    NoiseSuppress *_noiseSuppress;
+
+};
+
+
+class AudioRtpRecordHandler {
+public:
+	AudioRtpRecordHandler();
+	virtual ~AudioRtpRecordHandler();
+
+    /**
+     *  Set rtp media for this session
+     */
+    void setRtpMedia(AudioCodec* audioCodec);
+
+	int getCodecPayloadType(void) { return _audioRtpRecord.getCodecPayloadType(); }
+
+	int getCodecSampleRate(void) { return _audioRtpRecord.getCodecSampleRate(); }
+
+	int getCodecFrameSize(void) { return _audioRtpRecord.getCodecFrameSize(); }
+
+	int getHasDynamicPayload(void) { return _audioRtpRecord.getHasDynamicPayload(); }
+
+	int getAudioLayerFrameSize(void) { return _audioRtpRecord.getAudioLayerFrameSize(); }
+
+	int getAudioLayerSampleRate(void) { return _audioRtpRecord.getAudioLayerSampleRate(); }
+
+	EventQueue *getEventQueue(void) { return _audioRtpRecord.getEventQueue(); }
+
+	int getEventQueueSize(void) { return _audioRtpRecord.getEventQueueSize(); }
+
+	unsigned char *getEncodedData(void) {return _audioRtpRecord.getEncodedData(); }
+
+	inline float computeCodecFrameSize (int codecSamplePerFrame, int codecClockRate) {
+		return ( (float) codecSamplePerFrame * 1000.0) / (float) codecClockRate;
+	}
+
+	int computeNbByteAudioLayer (float codecFrameSize) {
+	    return (int) ( ( (float) _audioRtpRecord.getCodecSampleRate() * codecFrameSize * sizeof (SFLDataFormat)) / 1000.0);
+	}
+
+	void init(void);
+
+     /**
+      * Allocate memory for RTP buffers and fill them with zeros
+ 	 * @prereq Session codec needs to be initialized prior calling this method
+      */
+     void initBuffers (void);
+
+    /**
+     * Encode audio data from mainbuffer
+     */
+    int processDataEncode (void);
+
+    /**
+     * Decode audio data received from peer
+     */
+    void processDataDecode (unsigned char * spkrData, unsigned int size);
+
+    /**
+    * Ramp In audio data to avoid audio click from peer
+    */
+    bool fadeIn (SFLDataFormat *audio, int size, SFLDataFormat *factor);
+
+private:
+
+    AudioRtpRecord	_audioRtpRecord;
+
+};
+
+}
+
+#endif /* AUDIORTPRECORD_H_ */
diff --git a/sflphone-common/src/audio/audiortp/AudioRtpSession.cpp b/sflphone-common/src/audio/audiortp/AudioRtpSession.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..64d92c5e674befb47678ed68bb0c5c93e1a85af8
--- /dev/null
+++ b/sflphone-common/src/audio/audiortp/AudioRtpSession.cpp
@@ -0,0 +1,329 @@
+/*
+ *  Copyright (C) 2004, 2005, 2006, 2009, 2008, 2009, 2010 Savoir-Faire Linux Inc.
+ *  Author: Pierre-Luc Bacon <pierre-luc.bacon@savoirfairelinux.com>
+ *  Author: Alexandre Bourget <alexandre.bourget@savoirfairelinux.com>
+ *  Author: Laurielle Lea <laurielle.lea@savoirfairelinux.com>
+ *  Author: Emmanuel Milou <emmanuel.milou@savoirfairelinux.com>
+ *  Author: Yan Morin <yan.morin@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.
+ *
+ *  Additional permission under GNU GPL version 3 section 7:
+ *
+ *  If you modify this program, or any covered work, by linking or
+ *  combining it with the OpenSSL project's OpenSSL library (or a
+ *  modified version of that library), containing parts covered by the
+ *  terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc.
+ *  grants you additional permission to convey the resulting work.
+ *  Corresponding Source for a non-source form of such a combination
+ *  shall include the source code for the parts of OpenSSL used as well
+ *  as that of the covered work.
+ */
+
+#include "AudioRtpSession.h"
+
+namespace sfl
+{
+
+AudioRtpSession::AudioRtpSession (ManagerImpl * manager, SIPCall * sipcall) :
+		ost::SymmetricRTPSession (ost::InetHostAddress (sipcall->getLocalIp().c_str()), sipcall->getLocalAudioPort())
+																			, _time (new ost::Time())
+        																	, _mainloopSemaphore (0)
+        																	, _manager (manager)
+        																	, _timestamp (0)
+        																	, _timestampIncrement (0)
+        																	, _timestampCount (0)
+        																	, _countNotificationTime (0)
+        																	, _ca (sipcall)
+{
+	setCancel (cancelDefault);
+
+    assert (_ca);
+
+    _info ("AudioRtpSession: Local audio port %i will be used", _ca->getLocalAudioPort());
+
+}
+
+AudioRtpSession::~AudioRtpSession()
+{
+    _debug ("AudioRtpSession: Delete AudioRtpSession instance");
+
+    try {
+    	terminate();
+    } catch (...) {
+        _debugException ("AudioRtpSession: Thread destructor didn't terminate correctly");
+        throw;
+    }
+
+    _manager->getAudioDriver()->getMainBuffer()->unBindAll (_ca->getCallId());
+
+    if(_time)
+    	delete _time;
+    _time = NULL;
+
+}
+
+void AudioRtpSession::setSessionTimeouts (void)
+{
+	setSchedulingTimeout (sfl::schedulingTimeout);
+	setExpireTimeout (sfl::expireTimeout);
+}
+
+void AudioRtpSession::setSessionMedia (AudioCodec* audioCodec)
+{
+	// set internal codec info for this session
+	setRtpMedia(audioCodec);
+
+	// store codec info locally
+	int payloadType = getCodecPayloadType();
+	int frameSize = getCodecFrameSize();
+	int smplRate = getCodecSampleRate();
+	bool dynamic = getHasDynamicPayload();
+
+    // G722 requires timestamp to be incremented at 8 kHz
+    if (payloadType == 9)
+        _timestampIncrement = 160;
+    else
+        _timestampIncrement = frameSize;
+
+    _debug ("AudioRtpSession: Codec sampling rate: %d", smplRate);
+    _debug ("AudioRtpSession: Codec frame size: %d", frameSize);
+    _debug ("AudioRtpSession: 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));
+    } else if (dynamic) {
+        _debug ("AudioRtpSession: Setting dynamic payload format");
+        setPayloadFormat (ost::DynamicPayloadFormat ( (ost::PayloadType) payloadType, smplRate));
+    } else if (dynamic && payloadType != 9) {
+        _debug ("AudioRtpSession: Setting static payload format");
+        setPayloadFormat (ost::StaticPayloadFormat ( (ost::StaticPayloadType) payloadType));
+    }
+
+}
+
+void AudioRtpSession::setDestinationIpAddress (void)
+{
+    if (_ca == NULL) {
+        _error ("AudioRtpSession: 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!",
+               _ca->getLocalSDP()->get_remote_ip().data());
+        return;
+    }
+
+    // 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",
+           _ca->getLocalSDP()->get_remote_ip().data(), _remote_port);
+
+    if (!addDestination (_remote_ip, _remote_port)) {
+        _warn ("AudioRtpSession: Can't add new destination to session!");
+        return;
+    }
+}
+
+void AudioRtpSession::updateDestinationIpAddress (void)
+{
+    // 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");
+
+    // new destination is stored in call
+    // we just need to recall this method
+    setDestinationIpAddress();
+}
+
+void AudioRtpSession::sendDtmfEvent (sfl::DtmfEvent *dtmf)
+{
+    _debug ("AudioRtpSession: Send Dtmf %d", getEventQueueSize());
+
+    _timestamp += 160;
+
+    // discard equivalent size of audio
+    processDataEncode();
+
+    // change Payload type for DTMF payload
+    setPayloadFormat (ost::DynamicPayloadFormat ( (ost::PayloadType) 101, 8000));
+
+    // Set marker in case this is a new Event
+    if (dtmf->newevent)
+        setMark (true);
+
+    putData (_timestamp, (const unsigned char*) (& (dtmf->payload)), sizeof (ost::RTPPacket::RFC2833Payload));
+
+    // This is no more a new event
+    if (dtmf->newevent) {
+        dtmf->newevent = false;
+        setMark (false);
+    }
+
+    // get back the payload to audio
+    setPayloadFormat (ost::StaticPayloadFormat ( (ost::StaticPayloadType) getCodecPayloadType()));
+
+    // decrease length remaining to process for this event
+    dtmf->length -= 160;
+
+    dtmf->payload.duration += 1;
+
+    // next packet is going to be the last one
+    if ( (dtmf->length - 160) < 160)
+        dtmf->payload.ebit = true;
+
+    if (dtmf->length < 160) {
+        delete dtmf;
+        getEventQueue()->pop_front();
+    }
+}
+
+bool onRTPPacketRecv (ost::IncomingRTPPkt&)
+{
+    _debug ("AudioRtpSession: onRTPPacketRecv");
+
+    return true;
+}
+
+
+void AudioRtpSession::sendMicData()
+{
+    // Increment timestamp for outgoing packet
+    _timestamp += _timestampIncrement;
+
+    int compSize = processDataEncode();
+
+    // putData put the data on RTP queue, sendImmediate bypass this queue
+    putData (_timestamp, getEncodedData(), compSize);
+}
+
+
+void AudioRtpSession::receiveSpeakerData ()
+{
+    const ost::AppDataUnit* adu = NULL;
+
+    int packetTimestamp = getFirstTimestamp();
+
+    adu = getData (packetTimestamp);
+
+    if (!adu) {
+        return;
+    }
+
+    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");
+    }
+
+    // DTMF over RTP, size must be over 4 in order to process it as voice data
+    if (size > 4) {
+        processDataDecode (spkrDataIn, size);
+    }
+
+    delete adu;
+}
+
+
+int AudioRtpSession::startRtpThread (AudioCodec* audiocodec)
+{
+    _debug ("RTP: Starting main thread");
+    setSessionTimeouts();
+    setSessionMedia (audiocodec);
+    initBuffers();
+    return start (_mainloopSemaphore);
+}
+
+void AudioRtpSession::run ()
+{
+
+    // Timestamp must be initialized randomly
+    _timestamp = getCurrentTimestamp();
+
+    int threadSleep = 0;
+
+    if (getCodecSampleRate() != 0) {
+        threadSleep = (getCodecFrameSize() * 1000) / getCodecSampleRate();
+    } else {
+    	// TODO should not be dependent of audio layer frame size
+        threadSleep = getAudioLayerFrameSize();
+    }
+
+    TimerPort::setTimer (threadSleep);
+
+    // Set recording sampling rate
+    _ca->setRecordingSmplRate (getCodecSampleRate());
+
+    // 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());
+
+    while (!testCancel()) {
+
+        // Reset timestamp to make sure the timing information are up to date
+        if (_timestampCount > RTP_TIMESTAMP_RESET_FREQ) {
+            _timestamp = getCurrentTimestamp();
+            _timestampCount = 0;
+        }
+
+        _timestampCount++;
+
+        _manager->getAudioLayerMutex()->enter();
+
+        // TODO should not be linked to audio layer here
+        // converterSamplingRate = _audiolayer->getMainBuffer()->getInternalSamplingRate();
+        // _converterSamplingRate = _manager->getAudioDriver()->getMainBuffer()->getInternalSamplingRate();
+
+        // Send session
+        if (getEventQueueSize() > 0) {
+            sendDtmfEvent (getEventQueue()->front());
+        } else {
+            sendMicData ();
+        }
+
+        // Recv session
+        // TODO should not be called here anymore
+        // receiveSpeakerData ();
+
+        _manager->getAudioLayerMutex()->leave();
+
+        // Let's wait for the next transmit cycle
+        Thread::sleep (TimerPort::getTimer());
+        TimerPort::incTimer (threadSleep);
+    }
+
+    _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 2483b56bdc3041b79afa7fbf3bc97fe0a58681bc..07d215df1da59cca650a0c786eab27c82bc25e5d 100644
--- a/sflphone-common/src/audio/audiortp/AudioRtpSession.h
+++ b/sflphone-common/src/audio/audiortp/AudioRtpSession.h
@@ -40,13 +40,13 @@
 
 #include "global.h"
 
+#include "AudioRtpRecordHandler.h"
 #include "sip/sipcall.h"
 #include "sip/sdp.h"
 #include "audio/audiolayer.h"
 #include "audio/codecs/audiocodec.h"
-#include "audio/samplerateconverter.h"
-#include "audio/audioprocessing.h"
-#include "audio/noisesuppress.h"
+
+
 
 #include "managerimpl.h"
 
@@ -77,17 +77,9 @@ class AudioRtpSessionException: public std::exception
         }
 };
 
-typedef struct DtmfEvent {
-    ost::RTPPacket::RFC2833Payload payload;
-    int length;
-    bool newevent;
-} DtmfEvent;
-
-typedef list<DtmfEvent *> EventQueue;
-
 
-template <typename D>
-class AudioRtpSession : public ost::Thread, public ost::TimerPort
+// class AudioRtpSession : public ost::Thread, public ost::TimerPort, public AudioRtpRecordHandler, public ost::SymmetricRTPSession
+class AudioRtpSession : public ost::TimerPort, public ost::SymmetricRTPSession, public AudioRtpRecordHandler
 {
     public:
         /**
@@ -118,21 +110,8 @@ class AudioRtpSession : public ost::Thread, public ost::TimerPort
         */
         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:
 
-        /**
-         * Allocate memory for RTP buffers and fill them with zeros
-         */
-        void initBuffers (void);
-
         /**
          * Set RTP Sockets send/receive timeouts
          */
@@ -148,15 +127,6 @@ class AudioRtpSession : public ost::Thread, public ost::TimerPort
          */
         void setDestinationIpAddress (void);
 
-        /**
-         * Encode audio data from mainbuffer
-         */
-        int processDataEncode (void);
-
-        /**
-         * Decode audio data received from peer
-         */
-        void processDataDecode (unsigned char * spkrData, unsigned int size);
 
         /**
          * Send encoded data to peer
@@ -168,11 +138,6 @@ class AudioRtpSession : public ost::Thread, public ost::TimerPort
          */
         void receiveSpeakerData ();
 
-        /**
-        * Ramp In audio data to avoid audio click from peer
-        */
-        bool fadeIn (SFLDataFormat *audio, int size, SFLDataFormat *factor);
-
         ost::Time * _time;
 
         // This semaphore is not used
@@ -195,62 +160,12 @@ class AudioRtpSession : public ost::Thread, public ost::TimerPort
         // this destination and update a new one
         unsigned short _remote_port;
 
-        // Pointer to the session's codec
-        AudioCodec * _audiocodec;
-
-        // Pointer to audio layer
-        AudioLayer * _audiolayer;
-
-        /** 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;
-
-        /** 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;
 
         /**
          * Manager instance.
          */
         ManagerImpl * _manager;
 
-        /**
-         * Sampling rate of audio converter
-         */
-        int _converterSamplingRate;
-
         /**
          * Timestamp for this session
          */
@@ -272,660 +187,12 @@ class AudioRtpSession : public ost::Thread, public ost::TimerPort
          */
         int _countNotificationTime;
 
-        /**
-         * EventQueue used to store list of DTMF-
-         */
-        EventQueue _eventQueue;
-
-        /**
-         * Packet size in ms
-         */
-        int _packetLength;
-
-        int _ts;
-
-        /**
-         * Current time in ms
-         */
-        int _currentTime;
-
-        /**
-         * State of mic fade in
-         */
-        bool _micFadeInComplete;
-
-        /**
-           * State of spkr fade in
-         */
-        bool _spkrFadeInComplete;
-
-        /**
-         * Ampliturde factor to fade in mic data
-         */
-        SFLDataFormat _micAmplFactor;
-
-        /**
-         * Amplitude factor to fade in spkr data
-         */
-        SFLDataFormat _spkrAmplFactor;
-
-        /**
-         * Audio process containing noise reduction engine
-         */
-        AudioProcessing *_audioProcess;
-
-        /**
-         * Noise reduction engine
-         */
-        NoiseSuppress *_noiseSuppress;
 
     protected:
 
         SIPCall * _ca;
-
-        bool onRTPPacketRecv (ost::IncomingRTPPkt&);
 };
 
-template <typename D>
-AudioRtpSession<D>::AudioRtpSession (ManagerImpl * manager, SIPCall * sipcall) :
-        _time (new ost::Time()),
-        _mainloopSemaphore (0),
-        _audiocodec (NULL),
-        _audiolayer (NULL),
-        _micData (NULL),
-        _micDataConverted (NULL),
-        _micDataEncoded (NULL),
-        _spkrDataDecoded (NULL),
-        _spkrDataConverted (NULL),
-        _converter (NULL),
-        _layerSampleRate (0),
-        _codecSampleRate (0),
-        _layerFrameSize (0),
-        _manager (manager),
-        _converterSamplingRate (0),
-        _timestamp (0),
-        _timestampIncrement (0),
-        _timestampCount (0),
-        _countNotificationTime (0),
-        _micFadeInComplete (false),
-        _spkrFadeInComplete (false),
-        _micAmplFactor (32000),
-        _spkrAmplFactor (32000),
-        _audioProcess (NULL),
-        _noiseSuppress (NULL),
-        _ca (sipcall)
-{
-    setCancel (cancelDefault);
-
-    assert (_ca);
-
-    _info ("Rtp: Local audio port %i will be used", _ca->getLocalAudioPort());
-
-    //mic, we receive from soundcard in stereo, and we send encoded
-    _audiolayer = _manager->getAudioDriver();
-
-    if (_audiolayer == NULL) {
-        throw AudioRtpSessionException();
-    }
-
-    _layerFrameSize = _audiolayer->getFrameSize(); // in ms
-    _layerSampleRate = _audiolayer->getSampleRate();
-
-    _ts= 0;
-    _packetLength = 20;
-    _currentTime = 0;
-
-}
-
-template <typename D>
-AudioRtpSession<D>::~AudioRtpSession()
-{
-    _debug ("RTP: Delete AudioRtpSession instance");
-
-    try {
-        terminate();
-    } catch (...) {
-        _debugException ("Thread destructor didn't terminate correctly");
-        throw;
-    }
-
-    _manager->getAudioDriver()->getMainBuffer()->unBindAll (_ca->getCallId());
-
-    if (_micData) {
-        delete [] _micData;
-        _micData = NULL;
-    }
-
-    if (_micDataConverted) {
-        delete [] _micDataConverted;
-        _micDataConverted = NULL;
-    }
-
-    if (_micDataEncoded) {
-        delete [] _micDataEncoded;
-        _micDataEncoded = NULL;
-    }
-
-    if (_spkrDataDecoded) {
-        delete [] _spkrDataDecoded;
-        _spkrDataDecoded = NULL;
-    }
-
-    if (_spkrDataConverted) {
-        delete [] _spkrDataConverted;
-        _spkrDataConverted = NULL;
-    }
-
-    delete _time;
-    delete _converter;
-
-    if (_audiocodec) {
-        delete _audiocodec;
-        _audiocodec = NULL;
-    }
-
-    if (_audioProcess) {
-        delete _audioProcess;
-        _audioProcess = NULL;
-    }
-
-    if (_noiseSuppress) {
-        delete _noiseSuppress;
-        _noiseSuppress = NULL;
-    }
-}
-
-template <typename D>
-void AudioRtpSession<D>::initBuffers()
-{
-    // Set sampling rate, main buffer choose the highest one
-    _manager->getAudioDriver()->getMainBuffer()->setInternalSamplingRate (_codecSampleRate);
-
-    // may be different than one already set
-    _converterSamplingRate = _manager->getAudioDriver()->getMainBuffer()->getInternalSamplingRate();
-
-    // initialize SampleRate converter using AudioLayer's sampling rate
-    // (internal buffers initialized with maximal sampling rate and frame size)
-    _converter = new SamplerateConverter (_layerSampleRate, _layerFrameSize);
-
-    int nbSamplesMax = (int) (_codecSampleRate * _layerFrameSize /1000) *2;
-    _micData = new SFLDataFormat[nbSamplesMax];
-    _micDataConverted = new SFLDataFormat[nbSamplesMax];
-    _micDataEncoded = new unsigned char[nbSamplesMax*2];
-    _spkrDataConverted = new SFLDataFormat[nbSamplesMax];
-    _spkrDataDecoded = new SFLDataFormat[nbSamplesMax];
-
-
-    memset (_micData, 0, nbSamplesMax*sizeof (SFLDataFormat));
-    memset (_micDataConverted, 0, nbSamplesMax*sizeof (SFLDataFormat));
-    memset (_micDataEncoded, 0, nbSamplesMax*2);
-    memset (_spkrDataConverted, 0, nbSamplesMax*sizeof (SFLDataFormat));
-    memset (_spkrDataDecoded, 0, nbSamplesMax*sizeof (SFLDataFormat));
-
-    _manager->addStream (_ca->getCallId());
-}
-
-template <typename D>
-void AudioRtpSession<D>::setSessionTimeouts (void)
-{
-    try {
-        static_cast<D*> (this)->setSchedulingTimeout (schedulingTimeout);
-        static_cast<D*> (this)->setExpireTimeout (expireTimeout);
-    } catch (...) {
-        _debugException ("AudioRtpSession: Initialization failed while setting timeouts");
-        throw AudioRtpSessionException();
-    }
-}
-
-template <typename D>
-void AudioRtpSession<D>::setSessionMedia (AudioCodec* audiocodec)
-{
-    _audiocodec = audiocodec;
-
-    _debug ("RTP: Init codec payload %i", _audiocodec->getPayload());
-
-    _codecSampleRate = _audiocodec->getClockRate();
-    _codecFrameSize = _audiocodec->getFrameSize();
-
-    // G722 requires timestamp to be incremented at 8 kHz
-    if (_audiocodec->getPayload() == 9)
-        _timestampIncrement = 160;
-    else
-        _timestampIncrement = _codecFrameSize;
-
-
-    _debug ("RTP: Codec sampling rate: %d", _codecSampleRate);
-    _debug ("RTP: Codec frame size: %d", _codecFrameSize);
-    _debug ("RTP: RTP timestamp increment: %d", _timestampIncrement);
-
-    // Even if specified as a 16 kHz codec, G722 requires rtp sending rate to be 8 kHz
-    if (_audiocodec->getPayload() == 9) {
-        _debug ("RTP: Setting G722 payload format");
-        static_cast<D*> (this)->setPayloadFormat (ost::DynamicPayloadFormat ( (ost::PayloadType) _audiocodec->getPayload(), _audiocodec->getClockRate()));
-    } else if (_audiocodec->hasDynamicPayload()) {
-        _debug ("RTP: Setting dynamic payload format");
-        static_cast<D*> (this)->setPayloadFormat (ost::DynamicPayloadFormat ( (ost::PayloadType) _audiocodec->getPayload(), _audiocodec->getClockRate()));
-    } else if (!_audiocodec->hasDynamicPayload() && _audiocodec->getPayload() != 9) {
-        _debug ("RTP: Setting static payload format");
-        static_cast<D*> (this)->setPayloadFormat (ost::StaticPayloadFormat ( (ost::StaticPayloadType) _audiocodec->getPayload()));
-    }
-
-}
-
-template <typename D>
-void AudioRtpSession<D>::setDestinationIpAddress (void)
-{
-    if (_ca == NULL) {
-        _error ("RTP: Sipcall is gone.");
-        throw AudioRtpSessionException();
-    }
-
-    _info ("RTP: 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 ("RTP: Target IP address (%s) is not correct!",
-               _ca->getLocalSDP()->get_remote_ip().data());
-        return;
-    }
-
-    // Store remote port in case we would need to forget current destination
-    _remote_port = (unsigned short) _ca->getLocalSDP()->get_remote_audio_port();
-
-    _info ("RTP: New remote address for session: %s:%d",
-           _ca->getLocalSDP()->get_remote_ip().data(), _remote_port);
-
-    if (! static_cast<D*> (this)->addDestination (_remote_ip, _remote_port)) {
-        _warn ("RTP: Can't add new destination to session!");
-        return;
-    }
-}
-
-template <typename D>
-void AudioRtpSession<D>::updateDestinationIpAddress (void)
-{
-    // Destination address are stored in a list in ccrtp
-    // This method remove the current destination entry
-
-    if (!static_cast<D*> (this)->forgetDestination (_remote_ip, _remote_port, _remote_port+1))
-        _warn ("RTP: Could not remove previous destination");
-
-    // new destination is stored in call
-    // we just need to recall this method
-    setDestinationIpAddress();
-}
-
-template<typename D>
-void AudioRtpSession<D>::putDtmfEvent (int digit)
-{
-
-    sfl::DtmfEvent *dtmf = new sfl::DtmfEvent();
-
-    dtmf->payload.event = digit;
-    dtmf->payload.ebit = false; 			// end of event bit
-    dtmf->payload.rbit = false;  		// reserved bit
-    dtmf->payload.duration = 1; 	        // duration for this event
-    dtmf->newevent = true;
-    dtmf->length = 1000;
-
-    _eventQueue.push_back (dtmf);
-
-    _debug ("RTP: Put Dtmf Event %d", _eventQueue.size());
-
-}
-
-template<typename D>
-void AudioRtpSession<D>::sendDtmfEvent (sfl::DtmfEvent *dtmf)
-{
-    _debug ("RTP: Send Dtmf %d", _eventQueue.size());
-
-    _timestamp += 160;
-
-    // discard equivalent size of audio
-    processDataEncode();
-
-    // change Payload type for DTMF payload
-    static_cast<D*> (this)->setPayloadFormat (ost::DynamicPayloadFormat ( (ost::PayloadType) 101, 8000));
-
-    // Set marker in case this is a new Event
-    if (dtmf->newevent)
-        static_cast<D*> (this)->setMark (true);
-
-    static_cast<D*> (this)->putData (_timestamp, (const unsigned char*) (& (dtmf->payload)), sizeof (ost::RTPPacket::RFC2833Payload));
-
-    // This is no more a new event
-    if (dtmf->newevent) {
-        dtmf->newevent = false;
-        static_cast<D*> (this)->setMark (false);
-    }
-
-    // get back the payload to audio
-    static_cast<D*> (this)->setPayloadFormat (ost::StaticPayloadFormat ( (ost::StaticPayloadType) _audiocodec->getPayload()));
-
-    // decrease length remaining to process for this event
-    dtmf->length -= 160;
-
-    dtmf->payload.duration += 1;
-
-    // next packet is going to be the last one
-    if ( (dtmf->length - 160) < 160)
-        dtmf->payload.ebit = true;
-
-    if (dtmf->length < 160) {
-        delete dtmf;
-        _eventQueue.pop_front();
-    }
-}
-
-template <typename D>
-bool onRTPPacketRecv (ost::IncomingRTPPkt&)
-{
-    _debug ("AudioRtpSession: onRTPPacketRecv");
-
-    return true;
-}
-
-
-template <typename D>
-int AudioRtpSession<D>::processDataEncode (void)
-{
-    assert (_audiocodec);
-    assert (_audiolayer);
-
-    int _mainBufferSampleRate = _manager->getAudioDriver()->getMainBuffer()->getInternalSamplingRate();
-
-    // 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 = _manager->getAudioDriver()->getMainBuffer()->availForGet (_ca->getCallId());
-
-    // set available byte to maxByteToGet
-    int bytesAvail = (availBytesFromMic < maxBytesToGet) ? availBytesFromMic : maxBytesToGet;
-
-    if (bytesAvail == 0) {
-        memset (_micDataEncoded, 0, sizeof (SFLDataFormat));
-        return _audiocodec->getFrameSize();
-    }
-
-    // Get bytes from micRingBuffer to data_from_mic
-    int nbSample = _manager->getAudioDriver()->getMainBuffer()->getData (_micData , bytesAvail, 100, _ca->getCallId()) / sizeof (SFLDataFormat);
-
-    if (!_micFadeInComplete)
-        _micFadeInComplete = fadeIn (_micData, nbSample, &_micAmplFactor);
-
-    if (nbSample == 0)
-        return nbSample;
-
-    // nb bytes to be sent over RTP
-    int compSize = 0;
-
-    // test if resampling is required
-    if (_audiocodec->getClockRate() != _mainBufferSampleRate) {
-        int nb_sample_up = nbSample;
-
-        _nSamplesMic = nbSample;
-
-        nbSample = _converter->downsampleData (_micData , _micDataConverted , _audiocodec->getClockRate(), _mainBufferSampleRate, nb_sample_up);
-
-        if (_manager->audioPreference.getNoiseReduce())
-            _audioProcess->processAudio (_micDataConverted, nbSample*sizeof (SFLDataFormat));
-
-        compSize = _audiocodec->codecEncode (_micDataEncoded, _micDataConverted, nbSample*sizeof (SFLDataFormat));
-
-    } else {
-
-        _nSamplesMic = nbSample;
-
-        if (_manager->audioPreference.getNoiseReduce())
-            _audioProcess->processAudio (_micData, nbSample*sizeof (SFLDataFormat));
-
-        // no resampling required
-        compSize = _audiocodec->codecEncode (_micDataEncoded, _micData, nbSample*sizeof (SFLDataFormat));
-
-    }
-
-    return compSize;
-}
-
-template <typename D>
-void AudioRtpSession<D>::processDataDecode (unsigned char * spkrData, unsigned int size)
-{
-    if (_audiocodec != NULL) {
-
-
-        int _mainBufferSampleRate = _manager->getAudioDriver()->getMainBuffer()->getInternalSamplingRate();
-
-        // 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);
-
-        if (!_spkrFadeInComplete)
-            _spkrFadeInComplete = fadeIn (_spkrDataDecoded, nbSample, &_spkrAmplFactor);
-
-        // test if resampling is required
-        if (_audiocodec->getClockRate() != _mainBufferSampleRate) {
-
-            // Do sample rate conversion
-            int nb_sample_down = nbSample;
-
-            nbSample = _converter->upsampleData (_spkrDataDecoded, _spkrDataConverted, _codecSampleRate, _mainBufferSampleRate, nb_sample_down);
-
-            // Store the number of samples for recording
-            _nSamplesSpkr = nbSample;
-
-            // put data in audio layer, size in byte
-            _manager->getAudioDriver()->getMainBuffer()->putData (_spkrDataConverted, nbSample * sizeof (SFLDataFormat), 100, _ca->getCallId());
-
-
-        } else {
-            // Store the number of samples for recording
-            _nSamplesSpkr = nbSample;
-
-            // put data in audio layer, size in byte
-            _manager->getAudioDriver()->getMainBuffer()->putData (_spkrDataDecoded, expandedSize, 100, _ca->getCallId());
-        }
-
-        // Notify (with a beep) an incoming call when there is already a call
-        if (_manager->incomingCallWaiting() > 0) {
-            _countNotificationTime += _time->getSecond();
-            int countTimeModulo = _countNotificationTime % 5000;
-
-            // _debug("countNotificationTime: %d\n", countNotificationTime);
-            // _debug("countTimeModulo: %d\n", countTimeModulo);
-            if ( (countTimeModulo - _countNotificationTime) < 0) {
-                _manager->notificationIncomingCall();
-            }
-
-            _countNotificationTime = countTimeModulo;
-        }
-
-    }
-}
-
-template <typename D>
-void AudioRtpSession<D>::sendMicData()
-{
-    // STEP:
-    //   1. get data from mic
-    //   2. convert it to int16 - good sample, good rate
-    //   3. encode it
-    //   4. send it
-
-    // Increment timestamp for outgoing packet
-    _timestamp += _timestampIncrement;
-
-    if (!_audiolayer) {
-        _debug ("No audiolayer available for MIC");
-        return;
-    }
-
-    if (!_audiocodec) {
-        _debug ("No audiocodec available for MIC");
-        return;
-    }
-
-    int compSize = processDataEncode();
-
-    // putData put the data on RTP queue, sendImmediate bypass this queue
-    static_cast<D*> (this)->putData (_timestamp, _micDataEncoded, compSize);
-}
-
-
-template <typename D>
-void AudioRtpSession<D>::receiveSpeakerData ()
-{
-
-    if (!_audiolayer) {
-        _debug ("No audiolayer available for speaker");
-        return;
-    }
-
-    if (!_audiocodec) {
-        _debug ("No audiocodec available for speaker");
-        return;
-    }
-
-    const ost::AppDataUnit* adu = NULL;
-
-    int packetTimestamp = static_cast<D*> (this)->getFirstTimestamp();
-
-    adu = static_cast<D*> (this)->getData (packetTimestamp);
-
-    if (!adu) {
-        return;
-    }
-
-    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 ("No RTP packet available !!!!!!!!!!!!!!!!!!!!!!!\n");
-    }
-
-    // DTMF over RTP, size must be over 4 in order to process it as voice data
-    if (size > 4) {
-        processDataDecode (spkrDataIn, size);
-    }
-
-    delete adu;
-}
-
-template <typename D>
-bool AudioRtpSession<D>::fadeIn (SFLDataFormat *audio, int size, SFLDataFormat *factor)
-{
-
-    // apply amplitude factor;
-    while (size) {
-        size--;
-        audio[size] /= *factor;
-    }
-
-    // decrease factor
-    *factor /= FADEIN_STEP_SIZE;
-
-    // if factor reach 0, thsi function should no be called anymore
-    if (*factor == 0)
-        return true;
-
-    return false;
-}
-
-template <typename D>
-int AudioRtpSession<D>::startRtpThread (AudioCodec* audiocodec)
-{
-    _debug ("RTP: Starting main thread");
-    setSessionTimeouts();
-    setSessionMedia (audiocodec);
-    initBuffers();
-    return start (_mainloopSemaphore);
-}
-
-template <typename D>
-void AudioRtpSession<D>::run ()
-{
-
-    // Timestamp must be initialized randomly
-    _timestamp = static_cast<D*> (this)->getCurrentTimestamp();
-
-    int threadSleep = 0;
-
-    if (_codecSampleRate != 0) {
-        threadSleep = (_codecFrameSize * 1000) / _codecSampleRate;
-    } else {
-        threadSleep = _layerFrameSize;
-    }
-
-    TimerPort::setTimer (threadSleep);
-
-    if (_audiolayer == NULL) {
-        _error ("RTP: Error: Audiolayer is null, cannot start the audio stream");
-        throw AudioRtpSessionException();
-    }
-
-    // Set recording sampling rate
-    _ca->setRecordingSmplRate (_audiocodec->getClockRate());
-
-    // init noise reduction process
-    _noiseSuppress = new NoiseSuppress (_codecFrameSize, _audiocodec->getClockRate());
-    _audioProcess = new AudioProcessing (_noiseSuppress);
-
-    // Start audio stream (if not started) AND flush all buffers (main and urgent)
-    _manager->getAudioDriver()->startStream();
-    static_cast<D*> (this)->startRunning();
-
-    _debug ("RTP: Entering mainloop for call %s",_ca->getCallId().c_str());
-
-    _manager->getAudioDriver()->getMainBuffer()->getInternalSamplingRate();
-
-    while (!testCancel()) {
-
-        // Reset timestamp to make sure the timing information are up to date
-        if (_timestampCount > RTP_TIMESTAMP_RESET_FREQ) {
-            _timestamp = static_cast<D*> (this)->getCurrentTimestamp();
-            _timestampCount = 0;
-        }
-
-        _timestampCount++;
-
-
-        _manager->getAudioLayerMutex()->enter();
-
-        // converterSamplingRate = _audiolayer->getMainBuffer()->getInternalSamplingRate();
-        _converterSamplingRate = _manager->getAudioDriver()->getMainBuffer()->getInternalSamplingRate();
-
-        // Send session
-        if (_eventQueue.size() > 0) {
-            sendDtmfEvent (_eventQueue.front());
-        } else {
-            sendMicData ();
-        }
-
-        // Recv session
-        receiveSpeakerData ();
-
-        _manager->getAudioLayerMutex()->leave();
-
-        // Let's wait for the next transmit cycle
-        Thread::sleep (TimerPort::getTimer());
-        TimerPort::incTimer (threadSleep);
-    }
-
-    _debug ("RTP: Left main loop for call%s", _ca->getCallId().c_str());
-}
-
 }
 #endif // __AUDIO_RTP_SESSION_H__
 
diff --git a/sflphone-common/src/audio/audiortp/AudioSrtpSession.h b/sflphone-common/src/audio/audiortp/AudioSrtpSession.h
index 281cff8d9cdd87e60925aec13a902716f3c071c2..0b24c4ec4b17de87f31e1cc16beca2b726d1033d 100644
--- a/sflphone-common/src/audio/audiortp/AudioSrtpSession.h
+++ b/sflphone-common/src/audio/audiortp/AudioSrtpSession.h
@@ -74,7 +74,7 @@ class SrtpException: public std::exception
         }
 };
 
-class AudioSrtpSession : public ost::SymmetricRTPSession, public AudioRtpSession<AudioSrtpSession>
+class AudioSrtpSession : public AudioRtpSession
 {
     public:
 
diff --git a/sflphone-common/src/audio/audiortp/AudioSymmetricRtpSession.h b/sflphone-common/src/audio/audiortp/AudioSymmetricRtpSession.h
index a2275e3b508da1727d365fb03c2bfb10ff8bee80..330c8122f261e157673d8fedc38f47ae06e980ab 100644
--- a/sflphone-common/src/audio/audiortp/AudioSymmetricRtpSession.h
+++ b/sflphone-common/src/audio/audiortp/AudioSymmetricRtpSession.h
@@ -37,13 +37,11 @@ class ManagerImpl;
 
 namespace sfl
 {
-class AudioSymmetricRtpSession : public ost::SymmetricRTPSession, public AudioRtpSession<AudioSymmetricRtpSession>
+class AudioSymmetricRtpSession : public AudioRtpSession
 {
     public:
-        AudioSymmetricRtpSession (ManagerImpl * manager, SIPCall * sipcall) :
-                ost::SymmetricRTPSession (ost::InetHostAddress (sipcall->getLocalIp().c_str()), sipcall->getLocalAudioPort()),
-                AudioRtpSession<AudioSymmetricRtpSession> (manager, sipcall) {
-            _debug ("AudioSymmetricRtpSession initialized\n");
+        AudioSymmetricRtpSession (ManagerImpl * manager, SIPCall * sipcall) : AudioRtpSession (manager, sipcall) {
+
         }
 };
 }
diff --git a/sflphone-common/src/audio/audiortp/AudioZrtpSession.cpp b/sflphone-common/src/audio/audiortp/AudioZrtpSession.cpp
index 6632bc2a61c63f87223b32b8447e13c6f5e4febe..c450b934121688a8e8aeec28ba9896322cf986b4 100644
--- a/sflphone-common/src/audio/audiortp/AudioZrtpSession.cpp
+++ b/sflphone-common/src/audio/audiortp/AudioZrtpSession.cpp
@@ -43,14 +43,47 @@ namespace sfl
 {
 
 AudioZrtpSession::AudioZrtpSession (ManagerImpl * manager, SIPCall * sipcall, const std::string& zidFilename) :
-        ost::SymmetricZRTPSession (ost::InetHostAddress (sipcall->getLocalIp().c_str()), sipcall->getLocalAudioPort()),
-        AudioRtpSession<AudioZrtpSession> (manager, sipcall),
-        _zidFilename (zidFilename)
+        ost::SymmetricZRTPSession (ost::InetHostAddress (sipcall->getLocalIp().c_str()), sipcall->getLocalAudioPort())
+																											  , _zidFilename (zidFilename)
+																											  , _time (new ost::Time())
+																											  , _mainloopSemaphore (0)
+																											  , _manager (manager)
+																											  , _timestamp (0)
+																											  , _timestampIncrement (0)
+																											  , _timestampCount (0)
+																											  , _countNotificationTime (0)
+																											  , _ca (sipcall)
 {
     _debug ("AudioZrtpSession initialized");
     initializeZid();
+
+    setCancel (cancelDefault);
+
+    assert (_ca);
+
+    _info ("AudioZrtpSession: Local audio port %i will be used", _ca->getLocalAudioPort());
+}
+
+AudioZrtpSession::~AudioZrtpSession()
+{
+	_debug ("AudioZrtpSession: Delete AudioRtpSession instance");
+
+	    try {
+	    	terminate();
+	    } catch (...) {
+	        _debugException ("AudioZrtpSession: Thread destructor didn't terminate correctly");
+	        throw;
+	    }
+
+	    _manager->getAudioDriver()->getMainBuffer()->unBindAll (_ca->getCallId());
+
+	    if(_time)
+	    	delete _time;
+	    _time = NULL;
 }
 
+
+
 void AudioZrtpSession::initializeZid (void)
 {
 
@@ -95,4 +128,256 @@ void AudioZrtpSession::initializeZid (void)
 
     return;
 }
+
+void AudioRtpSession::setSessionTimeouts (void)
+{
+	setSchedulingTimeout (sfl::schedulingTimeout);
+	setExpireTimeout (sfl::expireTimeout);
+}
+
+void AudioRtpSession::setSessionMedia (AudioCodec* audioCodec)
+{
+	// set internal codec info for this session
+	setRtpMedia(audioCodec);
+
+	// store codec info locally
+	int payloadType = getCodecPayloadType();
+	int frameSize = getCodecFrameSize();
+	int smplRate = getCodecSampleRate();
+	bool dynamic = getHasDynamicPayload();
+
+    // G722 requires timestamp to be incremented at 8 kHz
+    if (payloadType == 9)
+        _timestampIncrement = 160;
+    else
+        _timestampIncrement = frameSize;
+
+    _debug ("AudioRtpSession: Codec sampling rate: %d", smplRate);
+    _debug ("AudioRtpSession: Codec frame size: %d", frameSize);
+    _debug ("AudioRtpSession: 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));
+    } else if (dynamic) {
+        _debug ("AudioRtpSession: Setting dynamic payload format");
+        setPayloadFormat (ost::DynamicPayloadFormat ( (ost::PayloadType) payloadType, smplRate));
+    } else if (dynamic && payloadType != 9) {
+        _debug ("AudioRtpSession: Setting static payload format");
+        setPayloadFormat (ost::StaticPayloadFormat ( (ost::StaticPayloadType) payloadType));
+    }
+
+}
+
+void AudioRtpSession::setDestinationIpAddress (void)
+{
+    if (_ca == NULL) {
+        _error ("AudioRtpSession: 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!",
+               _ca->getLocalSDP()->get_remote_ip().data());
+        return;
+    }
+
+    // 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",
+           _ca->getLocalSDP()->get_remote_ip().data(), _remote_port);
+
+    if (!addDestination (_remote_ip, _remote_port)) {
+        _warn ("AudioRtpSession: Can't add new destination to session!");
+        return;
+    }
+}
+
+void AudioRtpSession::updateDestinationIpAddress (void)
+{
+    // 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");
+
+    // new destination is stored in call
+    // we just need to recall this method
+    setDestinationIpAddress();
+}
+
+void AudioRtpSession::sendDtmfEvent (sfl::DtmfEvent *dtmf)
+{
+    _debug ("AudioRtpSession: Send Dtmf %d", getEventQueueSize());
+
+    _timestamp += 160;
+
+    // discard equivalent size of audio
+    processDataEncode();
+
+    // change Payload type for DTMF payload
+    setPayloadFormat (ost::DynamicPayloadFormat ( (ost::PayloadType) 101, 8000));
+
+    // Set marker in case this is a new Event
+    if (dtmf->newevent)
+        setMark (true);
+
+    putData (_timestamp, (const unsigned char*) (& (dtmf->payload)), sizeof (ost::RTPPacket::RFC2833Payload));
+
+    // This is no more a new event
+    if (dtmf->newevent) {
+        dtmf->newevent = false;
+        setMark (false);
+    }
+
+    // get back the payload to audio
+    setPayloadFormat (ost::StaticPayloadFormat ( (ost::StaticPayloadType) getCodecPayloadType()));
+
+    // decrease length remaining to process for this event
+    dtmf->length -= 160;
+
+    dtmf->payload.duration += 1;
+
+    // next packet is going to be the last one
+    if ( (dtmf->length - 160) < 160)
+        dtmf->payload.ebit = true;
+
+    if (dtmf->length < 160) {
+        delete dtmf;
+        getEventQueue()->pop_front();
+    }
+}
+
+bool onRTPPacketRecv (ost::IncomingRTPPkt&)
+{
+    _debug ("AudioRtpSession: onRTPPacketRecv");
+
+    return true;
+}
+
+
+void AudioRtpSession::sendMicData()
+{
+    // Increment timestamp for outgoing packet
+    _timestamp += _timestampIncrement;
+
+    int compSize = processDataEncode();
+
+    // putData put the data on RTP queue, sendImmediate bypass this queue
+    putData (_timestamp, getEncodedData(), compSize);
+}
+
+
+void AudioRtpSession::receiveSpeakerData ()
+{
+    const ost::AppDataUnit* adu = NULL;
+
+    int packetTimestamp = getFirstTimestamp();
+
+    adu = getData (packetTimestamp);
+
+    if (!adu) {
+        return;
+    }
+
+    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");
+    }
+
+    // DTMF over RTP, size must be over 4 in order to process it as voice data
+    if (size > 4) {
+        processDataDecode (spkrDataIn, size);
+    }
+
+    delete adu;
+}
+
+
+int AudioRtpSession::startRtpThread (AudioCodec* audiocodec)
+{
+    _debug ("RTP: Starting main thread");
+    setSessionTimeouts();
+    setSessionMedia (audiocodec);
+    initBuffers();
+    return start (_mainloopSemaphore);
+}
+
+void AudioRtpSession::run ()
+{
+
+    // Timestamp must be initialized randomly
+    _timestamp = getCurrentTimestamp();
+
+    int threadSleep = 0;
+
+    if (getCodecSampleRate() != 0) {
+        threadSleep = (getCodecFrameSize() * 1000) / getCodecSampleRate();
+    } else {
+    	// TODO should not be dependent of audio layer frame size
+        threadSleep = getAudioLayerFrameSize();
+    }
+
+    TimerPort::setTimer (threadSleep);
+
+    // Set recording sampling rate
+    _ca->setRecordingSmplRate (getCodecSampleRate());
+
+    // 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());
+
+    while (!testCancel()) {
+
+        // Reset timestamp to make sure the timing information are up to date
+        if (_timestampCount > RTP_TIMESTAMP_RESET_FREQ) {
+            _timestamp = getCurrentTimestamp();
+            _timestampCount = 0;
+        }
+
+        _timestampCount++;
+
+        _manager->getAudioLayerMutex()->enter();
+
+        // TODO should not be linked to audio layer here
+        // converterSamplingRate = _audiolayer->getMainBuffer()->getInternalSamplingRate();
+        // _converterSamplingRate = _manager->getAudioDriver()->getMainBuffer()->getInternalSamplingRate();
+
+        // Send session
+        if (getEventQueueSize() > 0) {
+            sendDtmfEvent (getEventQueue()->front());
+        } else {
+            sendMicData ();
+        }
+
+        // Recv session
+        // TODO should not be called here anymore
+        // receiveSpeakerData ();
+
+        _manager->getAudioLayerMutex()->leave();
+
+        // Let's wait for the next transmit cycle
+        Thread::sleep (TimerPort::getTimer());
+        TimerPort::incTimer (threadSleep);
+    }
+
+    _debug ("AudioRtpSession: 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 4eb68d364d8a6e057dc74de65bf2d13e9706dcc2..c50b08662aecfa90d42539487dcedccd62af2c7d 100644
--- a/sflphone-common/src/audio/audiortp/AudioZrtpSession.h
+++ b/sflphone-common/src/audio/audiortp/AudioZrtpSession.h
@@ -31,7 +31,7 @@
 
 #include <libzrtpcpp/zrtpccrtp.h>
 
-#include "AudioRtpSession.h"
+#include "AudioRtpRecordHandler.h"
 
 class ManagerImpl;
 class SIPCall;
@@ -46,7 +46,7 @@ class ZrtpZidException: public std::exception
         }
 };
 
-class AudioZrtpSession : public ost::SymmetricZRTPSession, public AudioRtpSession<AudioZrtpSession>
+class AudioZrtpSession : public ost::TimerPort, public ost::SymmetricZRTPSession, public AudioRtpRecordHandler
 {
     public:
         AudioZrtpSession (ManagerImpl * manager, SIPCall * sipcall, const std::string& zidFilename);
@@ -54,6 +54,56 @@ class AudioZrtpSession : public ost::SymmetricZRTPSession, public AudioRtpSessio
     private:
         void initializeZid (void);
         std::string _zidFilename;
+
+        ost::Time * _time;
+
+        // This semaphore is not used
+        // but is needed in order to avoid
+        // ambiguous compiling problem.
+        // It is set to 0, and since it is
+        // optional in ost::thread, then
+        // it amounts to the same as doing
+        // start() with no semaphore at all.
+        ost::Semaphore * _mainloopSemaphore;
+
+        // Main destination address for this rtp session.
+        // Stored in case or reINVITE, which may require to forget
+        // this destination and update a new one.
+        ost::InetHostAddress _remote_ip;
+
+
+        // Main destination port for this rtp session.
+        // Stored in case reINVITE, which may require to forget
+        // this destination and update a new one
+        unsigned short _remote_port;
+
+        /**
+         * Manager instance.
+         */
+        ManagerImpl * _manager;
+
+        /**
+         * Timestamp for this session
+         */
+        int _timestamp;
+
+        /**
+         * Timestamp incrementation value based on codec period length (framesize)
+         * except for G722 which require a 8 kHz incrementation.
+         */
+        int _timestampIncrement;
+
+        /**
+         * Timestamp reset freqeuncy specified in number of packet sent
+         */
+        short _timestampCount;
+
+        /**
+         * Time counter used to trigger incoming call notification
+         */
+        int _countNotificationTime;
+
+        SIPCall * _ca;
 };
 
 }
diff --git a/sflphone-common/src/audio/audiortp/Makefile.am b/sflphone-common/src/audio/audiortp/Makefile.am
index d2ab3aaec714d9065241752748284fe4ea59a0c2..f75a5973ea2feff0ebab76bbd6e5d3fb3922262f 100644
--- a/sflphone-common/src/audio/audiortp/Makefile.am
+++ b/sflphone-common/src/audio/audiortp/Makefile.am
@@ -3,12 +3,15 @@ include $(top_srcdir)/globals.mak
 noinst_LTLIBRARIES = libaudiortp.la
 
 libaudiortp_la_SOURCES = \
+		AudioRtpSession.cpp \
+		AudioRtpRecordHandler.cpp \
 		AudioRtpFactory.cpp \
 		AudioZrtpSession.cpp \
 		ZrtpSessionCallback.cpp \
 		AudioSrtpSession.cpp
 
 noinst_HEADERS = \
+		AudioRtpRecordHandler.h \
 		AudioRtpFactory.h \
 		AudioRtpSession.h \
 		AudioSymmetricRtpSession.h \