From 8c5e5dd5b68bc25ccd881e25f3a7280425fb5821 Mon Sep 17 00:00:00 2001 From: Alexandre Savard <alexandre.savard@savoirfairelinux.com> Date: Fri, 16 Jul 2010 17:19:32 -0400 Subject: [PATCH] [#3366] Handle early media received from RTP --- sflphone-common/src/audio/alsa/alsalayer.cpp | 8 +- .../src/audio/audiortp/AudioRtpSession.h | 13 ++- .../audio/audiortp/AudioSymmetricRtpSession.h | 2 +- .../src/audio/pulseaudio/pulselayer.cpp | 11 +- sflphone-common/src/managerimpl.cpp | 46 ++++---- sippxml/testEarlyMedia.xml | 107 ++++++++++++++++++ 6 files changed, 150 insertions(+), 37 deletions(-) create mode 100644 sippxml/testEarlyMedia.xml diff --git a/sflphone-common/src/audio/alsa/alsalayer.cpp b/sflphone-common/src/audio/alsa/alsalayer.cpp index 89e6f41513..5c19f3da8c 100644 --- a/sflphone-common/src/audio/alsa/alsalayer.cpp +++ b/sflphone-common/src/audio/alsa/alsalayer.cpp @@ -947,7 +947,9 @@ void AlsaLayer::audioCallback(void) } else { - if (tone) { + normalAvailBytes = getMainBuffer()->availForGet(); + + if (tone && (normalAvailBytes <= 0)) { out = (SFLDataFormat *) malloc (playbackAvailBytes); tone->getNext (out, playbackAvailSmpl, spkrVolume); @@ -957,7 +959,7 @@ void AlsaLayer::audioCallback(void) out = 0; } - else if (file_tone && !_RingtoneHandle) { + else if (file_tone && !_RingtoneHandle && (normalAvailBytes <= 0)) { out = (SFLDataFormat *) malloc (playbackAvailBytes); file_tone->getNext (out, playbackAvailSmpl, spkrVolume); @@ -985,8 +987,6 @@ void AlsaLayer::audioCallback(void) } - - normalAvailBytes = getMainBuffer()->availForGet(); toGet = (normalAvailBytes < (int) maxNbBytesToGet) ? normalAvailBytes : maxNbBytesToGet; out = (SFLDataFormat*) malloc (maxNbBytesToGet); diff --git a/sflphone-common/src/audio/audiortp/AudioRtpSession.h b/sflphone-common/src/audio/audiortp/AudioRtpSession.h index 5144d37679..cd4f7edc3c 100644 --- a/sflphone-common/src/audio/audiortp/AudioRtpSession.h +++ b/sflphone-common/src/audio/audiortp/AudioRtpSession.h @@ -574,8 +574,10 @@ namespace sfl { // set available byte to maxByteToGet int bytesAvail = (availBytesFromMic < maxBytesToGet) ? availBytesFromMic : maxBytesToGet; - if (bytesAvail == 0) - return 0; + 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); @@ -693,6 +695,7 @@ namespace sfl { template <typename D> void AudioRtpSession<D>::receiveSpeakerData () { + if (!_audiolayer) { _debug ("No audiolayer available for speaker"); return; @@ -707,8 +710,9 @@ namespace sfl { int packetTimestamp = static_cast<D*>(this)->getFirstTimestamp(); adu = static_cast<D*>(this)->getData(packetTimestamp); - if(!adu) + if(!adu) { return; + } unsigned char* spkrDataIn = NULL; unsigned int size = 0; @@ -723,8 +727,6 @@ namespace sfl { spkrDataIn = (unsigned char*) adu->getData(); // data in char size = adu->getSize(); // size in char - - result = jb_put(_jbuffer, spkrDataIn, JB_TYPE_VOICE, _packetLength, _ts+=20, _currentTime); } @@ -758,6 +760,7 @@ namespace sfl { template <typename D> void AudioRtpSession<D>::run () { + // Timestamp must be initialized randomly _timestamp = static_cast<D*>(this)->getCurrentTimestamp(); diff --git a/sflphone-common/src/audio/audiortp/AudioSymmetricRtpSession.h b/sflphone-common/src/audio/audiortp/AudioSymmetricRtpSession.h index 0713f3db0c..c1260a6fc3 100644 --- a/sflphone-common/src/audio/audiortp/AudioSymmetricRtpSession.h +++ b/sflphone-common/src/audio/audiortp/AudioSymmetricRtpSession.h @@ -40,7 +40,7 @@ namespace sfl { { public: AudioSymmetricRtpSession(ManagerImpl * manager, SIPCall * sipcall) : - ost::SymmetricRTPSession(ost::InetHostAddress(sipcall->getLocalIp().c_str()), sipcall->getLocalAudioPort()), + ost::SymmetricRTPSession(ost::InetHostAddress(sipcall->getLocalIp().c_str()), sipcall->getLocalAudioPort()), AudioRtpSession<AudioSymmetricRtpSession>(manager, sipcall) { _debug("AudioSymmetricRtpSession initialized\n"); diff --git a/sflphone-common/src/audio/pulseaudio/pulselayer.cpp b/sflphone-common/src/audio/pulseaudio/pulselayer.cpp index 403ec11ad0..667f0cf272 100755 --- a/sflphone-common/src/audio/pulseaudio/pulselayer.cpp +++ b/sflphone-common/src/audio/pulseaudio/pulselayer.cpp @@ -798,7 +798,6 @@ void PulseLayer::writeToSpeaker (void) SFLDataFormat* out;// = (SFLDataFormat*)pa_xmalloc(framesPerBuffer); urgentAvailBytes = _urgentRingBuffer.AvailForGet(); - // available bytes to be written in pulseaudio internal buffer int writeableSize = pa_stream_writable_size (playback->pulseStream()); @@ -821,12 +820,16 @@ void PulseLayer::writeToSpeaker (void) } else { + // Get ringtone AudioLoop* tone = _manager->getTelephoneTone(); + // We must test if data have been received from network in case of early media + normalAvailBytes = getMainBuffer()->availForGet(); + // flush remaining samples in _urgentRingBuffer flushUrgent(); - if (tone != 0) { + if ((tone != 0) && (normalAvailBytes <= 0)) { if (playback->getStreamState() == PA_STREAM_READY) { @@ -845,9 +848,7 @@ void PulseLayer::writeToSpeaker (void) int maxNbBytesToGet = 0; - // test if audio resampling is needed - if (_mainBufferSampleRate && ( (int) _audioSampleRate != _mainBufferSampleRate)) { // upsamplefactor is used to compute the number of bytes to get in the ring buffer @@ -862,8 +863,6 @@ void PulseLayer::writeToSpeaker (void) } - normalAvailBytes = getMainBuffer()->availForGet(); - byteToGet = (normalAvailBytes < (int) (maxNbBytesToGet)) ? normalAvailBytes : maxNbBytesToGet; if (byteToGet) { diff --git a/sflphone-common/src/managerimpl.cpp b/sflphone-common/src/managerimpl.cpp index 8eafb6212d..662c7f1646 100755 --- a/sflphone-common/src/managerimpl.cpp +++ b/sflphone-common/src/managerimpl.cpp @@ -1355,38 +1355,42 @@ void ManagerImpl::addStream (const CallID& call_id) { if (participToConference(call_id)) { - // bind to conference participant - ConferenceMap::iterator iter = _conferencemap.find(call->getConfId()); + _debug("Manager: Add stream to conference"); - if (iter != _conferencemap.end()) { - Conference* conf = iter->second; + // bind to conference participant + ConferenceMap::iterator iter = _conferencemap.find(call->getConfId()); - conf->bindParticipant(call_id); + if (iter != _conferencemap.end()) { + Conference* conf = iter->second; - ParticipantSet participants = conf->getParticipantList(); - // reset ring buffer for all conference participant - ParticipantSet::iterator iter_p = participants.begin(); + conf->bindParticipant(call_id); - while (iter_p != participants.end()) { + ParticipantSet participants = conf->getParticipantList(); + // reset ring buffer for all conference participant + ParticipantSet::iterator iter_p = participants.begin(); - // to avoid puting onhold the call - // switchCall(""); - _audiodriver->getMainBuffer()->flush(*iter_p); + while (iter_p != participants.end()) { - iter_p++; - } + // to avoid puting onhold the call + // switchCall(""); + _audiodriver->getMainBuffer()->flush(*iter_p); + + iter_p++; + } - _audiodriver->getMainBuffer()->flush(default_id); - } + _audiodriver->getMainBuffer()->flush(default_id); + } } else { - // bind to main - getAudioDriver()->getMainBuffer()->bindCallID(call_id); + _debug("Manager: Add stream to call"); - // _audiodriver->getMainBuffer()->flush(default_id); - _audiodriver->flushUrgent(); - _audiodriver->flushMain(); + // bind to main + getAudioDriver()->getMainBuffer()->bindCallID(call_id); + + // _audiodriver->getMainBuffer()->flush(default_id); + _audiodriver->flushUrgent(); + _audiodriver->flushMain(); } diff --git a/sippxml/testEarlyMedia.xml b/sippxml/testEarlyMedia.xml new file mode 100644 index 0000000000..28f34ff4f0 --- /dev/null +++ b/sippxml/testEarlyMedia.xml @@ -0,0 +1,107 @@ +<?xml version="1.0" encoding="ISO-8859-1" ?> <!DOCTYPE scenario SYSTEM "sipp.dtd"> + +<!-- sudo sipp -sf testEarlyMedia.xml 127.0.0.1 -i 127.0.0.1 -p 5062 -l 1 -m 1 -mp 6000 --> + +<scenario name="Basic UAS responder"> + + <recv request="INVITE" crlf="true"> + </recv> + + + <send> + <![CDATA[ + + SIP/2.0 100 Ringing + [last_Via:] + [last_From:] + [last_To:];tag=[call_number] + [last_Call-ID:] + [last_CSeq:] + Contact: <sip:[local_ip]:[local_port];transport=[transport]> + Content-Length: 0 + + ]]> + </send> + + <send> + <![CDATA[ + + SIP/2.0 183 Trying + [last_Via:] + [last_From:] + [last_To:];tag=[call_number] + [last_Call-ID:] + [last_CSeq:] + Contact: <sip:[local_ip]:[local_port];transport=[transport]> + Content-Type: application/sdp + Content-Length: [len] + + v=0 + o=user1 53655765 2353687637 IN IP[local_ip_type] [local_ip] + s=- + c=IN IP[media_ip_type] [media_ip] + t=0 0 + m=audio [media_port] RTP/AVP 0 + a=rtpmap:0 PCMU/8000 + + ]]> + </send> + + <!-- Play a pre-recorded PCAP file (RTP stream) --> + <nop> + <action> + <exec play_pcap_audio="g711a.pcap"/> + </action> + </nop> + + <!-- Pause 8 seconds, which is approximately the duration of the --> + <!-- PCAP file --> + <pause milliseconds="8000"/> + + <send retrans="500"> + <![CDATA[ + + SIP/2.0 200 OK + [last_Via:] + [last_From:] + [last_To:];tag=[call_number] + [last_Call-ID:] + [last_CSeq:] + Contact: <sip:[local_ip]:[local_port];transport=[transport]> + Content-Length: [len] + + ]]> + </send> + + <recv request="ACK" + optional="true" + rtd="true" + crlf="true"> + </recv> + + <recv request="BYE"> + </recv> + + <send> + <![CDATA[ + + SIP/2.0 200 OK + [last_Via:] + [last_From:] + [last_To:] + [last_Call-ID:] + [last_CSeq:] + Contact: <sip:[local_ip]:[local_port];transport=[transport]> + Content-Length: 0 + + ]]> + </send> + + <pause milliseconds="4000"/> + + + <ResponseTimeRepartition value="10, 20, 30, 40, 50, 100, 150, 200"/> + + <CallLengthRepartition value="10, 50, 100, 500, 1000, 5000, 10000"/> + +</scenario> -- GitLab