From 00fc6a2124fe7c2eab32012feb985c0ab3b47f9f Mon Sep 17 00:00:00 2001 From: asavard <asavard@asavard-KT378AA-A2L-a6552f.(none)> Date: Wed, 27 Oct 2010 11:37:12 -0400 Subject: [PATCH] [#4367] Implement RTP main loop --- .../audio/audiortp/AudioRtpRecordHandler.cpp | 48 +++--- .../src/audio/audiortp/AudioRtpSession.cpp | 146 +++++++++++------- .../src/audio/audiortp/AudioRtpSession.h | 8 +- 3 files changed, 117 insertions(+), 85 deletions(-) diff --git a/sflphone-common/src/audio/audiortp/AudioRtpRecordHandler.cpp b/sflphone-common/src/audio/audiortp/AudioRtpRecordHandler.cpp index aa452d9308..7995247659 100644 --- a/sflphone-common/src/audio/audiortp/AudioRtpRecordHandler.cpp +++ b/sflphone-common/src/audio/audiortp/AudioRtpRecordHandler.cpp @@ -49,7 +49,6 @@ AudioRtpRecord::AudioRtpRecord(ManagerImpl *manager) : _audioCodec(NULL) , _codecSampleRate(0) , _audioLayerFrameSize(0) , _codecFrameSize(0) - , _converterSamplingRate(0) , _micFadeInComplete(false) , _spkrFadeInComplete(false) , _micAmplFactor(initFadeinFactor) @@ -149,11 +148,6 @@ SamplerateConverter *AudioRtpRecord::getConverter() const return _converter; } -int AudioRtpRecord::getConverterSamplingRate() const -{ - return _converterSamplingRate; -} - EventQueue *AudioRtpRecord::getEventQueue() { return &_eventQueue; @@ -254,10 +248,6 @@ void AudioRtpRecord::setConverter(SamplerateConverter *_converter) this->_converter = _converter; } -void AudioRtpRecord::setConverterSamplingRate(int _converterSamplingRate) -{ - this->_converterSamplingRate = _converterSamplingRate; -} void AudioRtpRecord::setEventQueue(EventQueue _eventQueue) { @@ -355,9 +345,6 @@ void AudioRtpRecordHandler::initBuffers() // Set sampling rate, main buffer choose the highest one Manager::instance().getAudioDriver()->getMainBuffer()->setInternalSamplingRate (getCodecSampleRate()); - // may be different than one already set - // _converterSamplingRate = Manager::instance().getAudioDriver()->getMainBuffer()->getInternalSamplingRate(); - // initialize SampleRate converter using AudioLayer's sampling rate // (internal buffers initialized with maximal sampling rate and frame size) _audioRtpRecord.setConverter(new SamplerateConverter (getAudioLayerSampleRate(), getAudioLayerFrameSize())); @@ -400,7 +387,7 @@ void AudioRtpRecordHandler::putDtmfEvent(int digit) int AudioRtpRecordHandler::processDataEncode(void) { - _debug("AudioProcessEncode"); + _debug("Process data encode"); AudioCodec *audioCodec = getAudioCodec(); AudioLayer *audioLayer = Manager::instance().getAudioDriver(); @@ -413,21 +400,33 @@ int AudioRtpRecordHandler::processDataEncode(void) assert(audioLayer); int mainBufferSampleRate = audioLayer->getMainBuffer()->getInternalSamplingRate(); + // compute codec framesize in ms float fixedCodecFramesize = computeCodecFrameSize(getCodecFrameSize(), getCodecSampleRate()); + // compute nb of byte to get coresponding to 20 ms at audio layer frame size (44.1 khz) int maxBytesToGet = computeNbByteAudioLayer(fixedCodecFramesize); + // available bytes inside ringbuffer int availBytesFromMic = audioLayer->getMainBuffer()->availForGet(_ca->getCallId()); + _debug(" avail byte from mic %d", availBytesFromMic); + + if(!(availBytesFromMic > 320)) + return 0; + // set available byte to maxByteToGet int bytesAvail = (availBytesFromMic < maxBytesToGet) ? availBytesFromMic : maxBytesToGet; + if(bytesAvail == 0){ memset(micDataEncoded, 0, sizeof (SFLDataFormat)); return getCodecFrameSize(); } // Get bytes from micRingBuffer to data_from_mic - int nbSample = audioLayer->getMainBuffer()->getData(micData, bytesAvail, 100, _ca->getCallId()) / sizeof (SFLDataFormat); + // int nbSample = audioLayer->getMainBuffer()->getData(micData, bytesAvail, 100, _ca->getCallId()) / sizeof (SFLDataFormat); + int nbSample = audioLayer->getMainBuffer()->getData(micData, 320, 100, _ca->getCallId()) / sizeof (SFLDataFormat); + + // process mic fade in if(!_audioRtpRecord.getMicFadeInComplete()) _audioRtpRecord.setMicFadeInComplete(fadeIn(micData, nbSample, _audioRtpRecord.getMicAmplFactor())); @@ -443,13 +442,13 @@ int AudioRtpRecordHandler::processDataEncode(void) int nbSampleUp = nbSample; nbSample = _audioRtpRecord.getConverter()->downsampleData(micData, micDataConverted, _audioRtpRecord.getCodecSampleRate(), mainBufferSampleRate, nbSampleUp); - if(Manager::instance().audioPreference.getNoiseReduce()) - _audioRtpRecord.getNoiseReductionProcess()->processAudio(micDataConverted, nbSample * sizeof (SFLDataFormat)); + // if(Manager::instance().audioPreference.getNoiseReduce()) + // _audioRtpRecord.getNoiseReductionProcess()->processAudio(micDataConverted, nbSample * sizeof (SFLDataFormat)); compSize = audioCodec->codecEncode(micDataEncoded, micDataConverted, nbSample * sizeof (SFLDataFormat)); }else{ - if(Manager::instance().audioPreference.getNoiseReduce()) - _audioRtpRecord.getNoiseReductionProcess()->processAudio(micData, nbSample * sizeof (SFLDataFormat)); + // if(Manager::instance().audioPreference.getNoiseReduce()) + // _audioRtpRecord.getNoiseReductionProcess()->processAudio(micData, nbSample * sizeof (SFLDataFormat)); // no resampling required compSize = audioCodec->codecEncode(micDataEncoded, micData, nbSample * sizeof (SFLDataFormat)); @@ -460,8 +459,6 @@ int AudioRtpRecordHandler::processDataEncode(void) void AudioRtpRecordHandler::processDataDecode(unsigned char *spkrData, unsigned int size) { - _debug("AudioProcessDecode"); - AudioCodec *audioCodec = getAudioCodec(); AudioLayer *audioLayer = Manager::instance().getAudioDriver(); @@ -471,7 +468,7 @@ void AudioRtpRecordHandler::processDataDecode(unsigned char *spkrData, unsigned SFLDataFormat *spkrDataDecoded = _audioRtpRecord.getSpkrDataConverted(); SFLDataFormat *spkrDataConverted = _audioRtpRecord.getSpkrDataDecoded(); - int mainBufferSampleRate = Manager::instance().getAudioDriver()->getMainBuffer()->getInternalSamplingRate(); + int mainBufferSampleRate = audioLayer->getMainBuffer()->getInternalSamplingRate(); // Return the size of data in bytes int expandedSize = audioCodec->codecDecode (spkrDataDecoded , spkrData , size); @@ -491,17 +488,18 @@ void AudioRtpRecordHandler::processDataDecode(unsigned char *spkrData, unsigned nbSample = _audioRtpRecord.getConverter()->upsampleData (spkrDataDecoded, spkrDataConverted, _audioRtpRecord.getCodecSampleRate(), mainBufferSampleRate, nbSampleDown); // put data in audio layer, size in byte - Manager::instance().getAudioDriver()->getMainBuffer()->putData (spkrDataConverted, nbSample * sizeof (SFLDataFormat), 100, _ca->getCallId()); + audioLayer->getMainBuffer()->putData (spkrDataConverted, nbSample * sizeof (SFLDataFormat), 100, _ca->getCallId()); } else { // put data in audio layer, size in byte - Manager::instance().getAudioDriver()->getMainBuffer()->putData (spkrDataDecoded, expandedSize, 100, _ca->getCallId()); + audioLayer->getMainBuffer()->putData (spkrDataDecoded, expandedSize, 100, _ca->getCallId()); } } bool AudioRtpRecordHandler::fadeIn(SFLDataFormat *audio, int size, SFLDataFormat *factor) { + /* // apply amplitude factor; while(size){ size--; @@ -515,6 +513,8 @@ bool AudioRtpRecordHandler::fadeIn(SFLDataFormat *audio, int size, SFLDataFormat return true; return false; + */ + return true; } } diff --git a/sflphone-common/src/audio/audiortp/AudioRtpSession.cpp b/sflphone-common/src/audio/audiortp/AudioRtpSession.cpp index 21d4c6ccbb..d80dde79f0 100644 --- a/sflphone-common/src/audio/audiortp/AudioRtpSession.cpp +++ b/sflphone-common/src/audio/audiortp/AudioRtpSession.cpp @@ -41,6 +41,11 @@ namespace sfl { +inline uint32 +timeval2microtimeout(const timeval& t) +{ return ((t.tv_sec * 1000000ul) + t.tv_usec); } + + AudioRtpSession::AudioRtpSession (ManagerImpl * manager, SIPCall * sipcall) : // ost::SymmetricRTPSession (ost::InetHostAddress (sipcall->getLocalIp().c_str()), sipcall->getLocalAudioPort()), AudioRtpRecordHandler(manager, sipcall), @@ -216,24 +221,33 @@ void AudioRtpSession::sendDtmfEvent (sfl::DtmfEvent *dtmf) getEventQueue()->pop_front(); } } -/* -bool onRTPPacketRecv (ost::IncomingRTPPkt&) + +bool AudioRtpSession::onRTPPacketRecv (ost::IncomingRTPPkt&) { - _debug ("AudioRtpSession: onRTPPacketRecv"); + //_debug ("AudioRtpSession: onRTPPacketRecv"); + + receiveSpeakerData (); return true; } -*/ + void AudioRtpSession::sendMicData() { - _debug("sendMicData"); + // _debug("============== sendMicData ==============="); + + int compSize = processDataEncode(); + + // If no data, return + if(!compSize) + return; // Increment timestamp for outgoing packet _timestamp += _timestampIncrement; - int compSize = processDataEncode(); + // _debug(" compSize: %d", compSize); + // _debug(" timestamp: %d", _timestamp); // putData put the data on RTP queue, sendImmediate bypass this queue putData (_timestamp, getMicDataEncoded(), compSize); @@ -242,7 +256,6 @@ void AudioRtpSession::sendMicData() void AudioRtpSession::receiveSpeakerData () { - _debug("receiveSpkrData"); const ost::AppDataUnit* adu = NULL; @@ -274,14 +287,31 @@ void AudioRtpSession::receiveSpeakerData () delete adu; } +void AudioRtpSession::notifyIncomingCall() +{ + // Notify (with a beep) an incoming call when there is already a call + if (Manager::instance().incomingCallWaiting() > 0) { + _countNotificationTime += _time->getSecond(); + int countTimeModulo = _countNotificationTime % 5000; + + // _debug("countNotificationTime: %d\n", countNotificationTime); + // _debug("countTimeModulo: %d\n", countTimeModulo); + if ( (countTimeModulo - _countNotificationTime) < 0) { + Manager::instance().notificationIncomingCall(); + } + _countNotificationTime = countTimeModulo; + } +} + int AudioRtpSession::startRtpThread (AudioCodec* audiocodec) { _debug ("AudioRtpSession: Starting main thread"); - initNoiseSuppress(); + // initNoiseSuppress(); setSessionTimeouts(); setSessionMedia (audiocodec); initBuffers(); + enableStack(); int ret = start (_mainloopSemaphore); return ret; } @@ -312,58 +342,54 @@ void AudioRtpSession::run () _debug ("AudioRtpSession: Entering mainloop for call %s",_ca->getCallId().c_str()); - // while (!static_cast<ost::Thread *>(this)->testCancel()) { - while (!testCancel()) { - - _debug("audio"); - - // 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 (); - - - - // Notify (with a beep) an incoming call when there is already a call - if (Manager::instance().incomingCallWaiting() > 0) { - _countNotificationTime += _time->getSecond(); - int countTimeModulo = _countNotificationTime % 5000; - - // _debug("countNotificationTime: %d\n", countNotificationTime); - // _debug("countTimeModulo: %d\n", countTimeModulo); - if ( (countTimeModulo - _countNotificationTime) < 0) { - Manager::instance().notificationIncomingCall(); - } - - _countNotificationTime = countTimeModulo; - } - - _manager->getAudioLayerMutex()->leave(); - - // Let's wait for the next transmit cycle - Thread::sleep (TimerPort::getTimer()); - TimerPort::incTimer (threadSleep); - } + uint32 timeout = 0; + while ( isActive() ) { + if ( timeout < 1000 ){ // !(timeout/1000) + timeout = getSchedulingTimeout(); + } + + _manager->getAudioLayerMutex()->enter(); + + // Send session + if (getEventQueueSize() > 0) { + sendDtmfEvent (getEventQueue()->front()); + } else { + sendMicData (); + } + + // Recv session + // TODO should not be called here anymore +// receiveSpeakerData (); + + notifyIncomingCall(); + + _manager->getAudioLayerMutex()->leave(); + + setCancel(cancelDeferred); + controlReceptionService(); + controlTransmissionService(); + setCancel(cancelImmediate); + uint32 maxWait = timeval2microtimeout(getRTCPCheckInterval()); + // make sure the scheduling timeout is + // <= the check interval for RTCP + // packets + timeout = (timeout > maxWait)? maxWait : timeout; + if ( timeout < 1000 ) { // !(timeout/1000) + setCancel(cancelDeferred); + dispatchDataPacket(); + setCancel(cancelImmediate); + timerTick(); + } else { + if ( isPendingData(timeout/1000) ) { + setCancel(cancelDeferred); + if (isActive()) { // take in only if active + takeInDataPacket(); + } + setCancel(cancelImmediate); + } + timeout = 0; + } + } _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 665dfe9cff..151a303178 100644 --- a/sflphone-common/src/audio/audiortp/AudioRtpSession.h +++ b/sflphone-common/src/audio/audiortp/AudioRtpSession.h @@ -73,6 +73,8 @@ class AudioRtpSession : protected ost::Thread, public ost::TimerPort, public Aud // Thread associated method virtual void run (); + virtual bool onRTPPacketRecv (ost::IncomingRTPPkt&); + int startRtpThread (AudioCodec*); /** @@ -105,7 +107,6 @@ class AudioRtpSession : protected ost::Thread, public ost::TimerPort, public Aud */ void setDestinationIpAddress (void); - /** * Send encoded data to peer */ @@ -116,6 +117,11 @@ class AudioRtpSession : protected ost::Thread, public ost::TimerPort, public Aud */ void receiveSpeakerData (); + /** + * Notificatify user with a beep for incoming calls + */ + void notifyIncomingCall(); + ost::Time * _time; // This semaphore is not used -- GitLab