diff --git a/EchoCanceller.cpp b/EchoCanceller.cpp old mode 100644 new mode 100755 index 2734de19cc..085f24690b --- a/EchoCanceller.cpp +++ b/EchoCanceller.cpp @@ -66,7 +66,7 @@ EchoCanceller::EchoCanceller(bool enableAEC, bool enableNS, bool enableAGC){ #else aec=webrtc::WebRtcAec_Create(); webrtc::WebRtcAec_Init(aec, 48000, 48000); - //webrtc::WebRtcAec_enable_delay_agnostic(webrtc::WebRtcAec_aec_core(aec), 1); + webrtc::WebRtcAec_enable_delay_agnostic(webrtc::WebRtcAec_aec_core(aec), 1); webrtc::AecConfig config; config.metricsMode=webrtc::kAecFalse; config.nlpMode=webrtc::kAecNlpAggressive; @@ -183,6 +183,8 @@ void EchoCanceller::RunBufferFarendThread(void* arg){ farendBufferPool->Reuse((unsigned char *) samplesIn); ((webrtc::SplittingFilter*)splittingFilterFarend)->Analysis(bufIn, bufOut); aecMutex.Lock(); + //outstandingFarendFrames++; + //LOGV("BufferFarend: %d frames", outstandingFarendFrames); #ifndef TGVOIP_USE_DESKTOP_DSP WebRtcAecm_BufferFarend(aec, bufOut->ibuf_const()->bands(0)[0], 160); WebRtcAecm_BufferFarend(aec, bufOut->ibuf_const()->bands(0)[0]+160, 160); @@ -318,6 +320,8 @@ void EchoCanceller::ProcessInput(unsigned char* data, unsigned char* out, size_t aecIn[i]+=160; } webrtc::WebRtcAec_Process(aec, aecIn, 3, aecOut, AEC_FRAME_SIZE, audio::AudioOutput::GetEstimatedDelay()+audio::AudioInput::GetEstimatedDelay(), 0); + //outstandingFarendFrames--; + //LOGV("Process: %d frames", outstandingFarendFrames); memcpy(bufOut->fbuf()->bands(0)[0], _aecOut[0], 320*4); memcpy(bufOut->fbuf()->bands(0)[1], _aecOut[1], 320*4); diff --git a/EchoCanceller.h b/EchoCanceller.h old mode 100644 new mode 100755 index a774abac2e..c80eeff75c --- a/EchoCanceller.h +++ b/EchoCanceller.h @@ -48,6 +48,7 @@ private: void* ns; // NsxHandle void* agc; int32_t agcMicLevel; + //int32_t outstandingFarendFrames=0; #endif }; diff --git a/VoIPController.h b/VoIPController.h index 7025fe821e..a5db31942f 100644 --- a/VoIPController.h +++ b/VoIPController.h @@ -32,7 +32,7 @@ #include "Buffers.h" #include "PacketReassembler.h" -#define LIBTGVOIP_VERSION "2.1" +#define LIBTGVOIP_VERSION "2.1.1" #ifdef _WIN32 #undef GetCurrentTime diff --git a/VoIPServerConfig.cpp b/VoIPServerConfig.cpp index bbc2188c2d..56cc6c4d6a 100644 --- a/VoIPServerConfig.cpp +++ b/VoIPServerConfig.cpp @@ -7,6 +7,8 @@ #include "VoIPServerConfig.h" #include #include "logging.h" +#include +#include using namespace tgvoip; @@ -40,12 +42,12 @@ double ServerConfig::GetDouble(std::string name, double fallback){ MutexGuard sync(mutex); if(ContainsKey(name)){ std::string val=config[name]; - char* end; - const char* start=val.c_str(); - double d=strtod(start, &end); - if(end!=start){ - return d; - } + std::istringstream stm(val); + double rval=fallback; + stm.imbue(std::locale("C")); + stm >> rval; + if(!stm.fail()) + return rval; } return fallback; } diff --git a/os/linux/AudioInputPulse.cpp b/os/linux/AudioInputPulse.cpp index a7769417b7..5e8a0fa445 100644 --- a/os/linux/AudioInputPulse.cpp +++ b/os/linux/AudioInputPulse.cpp @@ -65,8 +65,8 @@ AudioInputPulse::AudioInputPulse(std::string devID){ return; } pa_context_set_state_callback(context, AudioInputPulse::ContextStateCallback, this); - pa_threaded_mainloop_lock(mainloop); isLocked=true; + pa_threaded_mainloop_lock(mainloop); int err=pa_threaded_mainloop_start(mainloop); CHECK_ERROR(err, "pa_threaded_mainloop_start"); didStart=true; @@ -75,9 +75,7 @@ AudioInputPulse::AudioInputPulse(std::string devID){ CHECK_ERROR(err, "pa_context_connect"); while(true){ - pa_threaded_mainloop_lock(mainloop); pa_context_state_t contextState=pa_context_get_state(context); - pa_threaded_mainloop_unlock(mainloop); if(!PA_CONTEXT_IS_GOOD(contextState)){ LOGE("Error initializing PulseAudio (PA_CONTEXT_IS_GOOD)"); failed=true; @@ -147,8 +145,10 @@ void AudioInputPulse::Start(){ if(failed || isRecording) return; + pa_threaded_mainloop_lock(mainloop); isRecording=true; - pa_operation_unref(pa_stream_cork(stream, 0, AudioInputPulse::StreamSuccessCallback, mainloop)); + pa_operation_unref(pa_stream_cork(stream, 0, AudioInputPulse::StreamSuccessCallback, NULL)); + pa_threaded_mainloop_unlock(mainloop); } void AudioInputPulse::Stop(){ @@ -156,7 +156,9 @@ void AudioInputPulse::Stop(){ return; isRecording=false; - pa_operation_unref(pa_stream_cork(stream, 1, AudioInputPulse::StreamSuccessCallback, mainloop)); + pa_threaded_mainloop_lock(mainloop); + pa_operation_unref(pa_stream_cork(stream, 1, AudioInputPulse::StreamSuccessCallback, NULL)); + pa_threaded_mainloop_unlock(mainloop); } bool AudioInputPulse::IsRecording(){ @@ -164,6 +166,7 @@ bool AudioInputPulse::IsRecording(){ } void AudioInputPulse::SetCurrentDevice(std::string devID){ + pa_threaded_mainloop_lock(mainloop); currentDevice=devID; if(isRecording && isConnected){ pa_stream_disconnect(stream); @@ -171,13 +174,13 @@ void AudioInputPulse::SetCurrentDevice(std::string devID){ } pa_buffer_attr bufferAttr={ - .maxlength=960*6, - .tlength=960*6, - .prebuf=0, - .minreq=960*2 + .maxlength=(uint32_t)-1, + .tlength=(uint32_t)-1, + .prebuf=(uint32_t)-1, + .minreq=(uint32_t)-1, + .fragsize=960*2 }; - int streamFlags=PA_STREAM_START_CORKED | PA_STREAM_INTERPOLATE_TIMING | - PA_STREAM_NOT_MONOTONIC | PA_STREAM_AUTO_TIMING_UPDATE | PA_STREAM_ADJUST_LATENCY; + int streamFlags=PA_STREAM_START_CORKED | PA_STREAM_INTERPOLATE_TIMING | PA_STREAM_AUTO_TIMING_UPDATE | PA_STREAM_ADJUST_LATENCY; int err=pa_stream_connect_record(stream, devID=="default" ? NULL : devID.c_str(), &bufferAttr, (pa_stream_flags_t)streamFlags); if(err!=0 && devID!="default"){ @@ -187,9 +190,7 @@ void AudioInputPulse::SetCurrentDevice(std::string devID){ CHECK_ERROR(err, "pa_stream_connect_record"); while(true){ - pa_threaded_mainloop_lock(mainloop); pa_stream_state_t streamState=pa_stream_get_state(stream); - pa_threaded_mainloop_unlock(mainloop); if(!PA_STREAM_IS_GOOD(streamState)){ LOGE("Error connecting to audio device '%s'", devID.c_str()); failed=true; @@ -205,6 +206,7 @@ void AudioInputPulse::SetCurrentDevice(std::string devID){ if(isRecording){ pa_operation_unref(pa_stream_cork(stream, 0, AudioInputPulse::StreamSuccessCallback, mainloop)); } + pa_threaded_mainloop_unlock(mainloop); } bool AudioInputPulse::EnumerateDevices(std::vector& devs){ diff --git a/os/linux/AudioOutputPulse.cpp b/os/linux/AudioOutputPulse.cpp index 859c22c656..b29fea3c9e 100644 --- a/os/linux/AudioOutputPulse.cpp +++ b/os/linux/AudioOutputPulse.cpp @@ -150,7 +150,9 @@ void AudioOutputPulse::Start(){ return; isPlaying=true; - pa_operation_unref(pa_stream_cork(stream, 0, AudioOutputPulse::StreamSuccessCallback, mainloop)); + pa_threaded_mainloop_lock(mainloop); + pa_operation_unref(pa_stream_cork(stream, 0, AudioOutputPulse::StreamSuccessCallback, NULL)); + pa_threaded_mainloop_unlock(mainloop); } void AudioOutputPulse::Stop(){ @@ -158,7 +160,9 @@ void AudioOutputPulse::Stop(){ return; isPlaying=false; - pa_operation_unref(pa_stream_cork(stream, 1, AudioOutputPulse::StreamSuccessCallback, mainloop)); + pa_threaded_mainloop_lock(mainloop); + pa_operation_unref(pa_stream_cork(stream, 1, AudioOutputPulse::StreamSuccessCallback, NULL)); + pa_threaded_mainloop_unlock(mainloop); } bool AudioOutputPulse::IsPlaying(){ @@ -166,6 +170,7 @@ bool AudioOutputPulse::IsPlaying(){ } void AudioOutputPulse::SetCurrentDevice(std::string devID){ + pa_threaded_mainloop_lock(mainloop); currentDevice=devID; if(isPlaying && isConnected){ pa_stream_disconnect(stream); @@ -173,13 +178,13 @@ void AudioOutputPulse::SetCurrentDevice(std::string devID){ } pa_buffer_attr bufferAttr={ - .maxlength=960*6, - .tlength=960*6, - .prebuf=0, - .minreq=960*2 + .maxlength=(uint32_t)-1, + .tlength=960*2, + .prebuf=(uint32_t)-1, + .minreq=(uint32_t)-1, + .fragsize=(uint32_t)-1 }; - int streamFlags=PA_STREAM_START_CORKED | PA_STREAM_INTERPOLATE_TIMING | - PA_STREAM_NOT_MONOTONIC | PA_STREAM_AUTO_TIMING_UPDATE | PA_STREAM_ADJUST_LATENCY; + int streamFlags=PA_STREAM_START_CORKED | PA_STREAM_INTERPOLATE_TIMING | PA_STREAM_AUTO_TIMING_UPDATE | PA_STREAM_ADJUST_LATENCY; int err=pa_stream_connect_playback(stream, devID=="default" ? NULL : devID.c_str(), &bufferAttr, (pa_stream_flags_t)streamFlags, NULL, NULL); if(err!=0 && devID!="default"){ @@ -189,9 +194,7 @@ void AudioOutputPulse::SetCurrentDevice(std::string devID){ CHECK_ERROR(err, "pa_stream_connect_playback"); while(true){ - pa_threaded_mainloop_lock(mainloop); pa_stream_state_t streamState=pa_stream_get_state(stream); - pa_threaded_mainloop_unlock(mainloop); if(!PA_STREAM_IS_GOOD(streamState)){ LOGE("Error connecting to audio device '%s'", devID.c_str()); failed=true; @@ -207,6 +210,7 @@ void AudioOutputPulse::SetCurrentDevice(std::string devID){ if(isPlaying){ pa_operation_unref(pa_stream_cork(stream, 0, AudioOutputPulse::StreamSuccessCallback, mainloop)); } + pa_threaded_mainloop_unlock(mainloop); } bool AudioOutputPulse::EnumerateDevices(std::vector& devs){ @@ -270,40 +274,21 @@ void AudioOutputPulse::StreamWriteCallback(pa_stream *stream, size_t requestedBy } void AudioOutputPulse::StreamWriteCallback(pa_stream *stream, size_t requestedBytes) { - int bytesRemaining = requestedBytes; - uint8_t *buffer = NULL; - while (bytesRemaining > 0) { - size_t bytesToFill = 102400; - size_t i; - - if (bytesToFill > bytesRemaining) bytesToFill = bytesRemaining; - - int err=pa_stream_begin_write(stream, (void**) &buffer, &bytesToFill); - CHECK_ERROR(err, "pa_stream_begin_write"); - + assert(requestedBytes<=sizeof(remainingData)); + while(requestedBytes>remainingDataSize){ if(isPlaying){ - while(remainingDataSize=sizeof(remainingData)){ - LOGE("Can't provide %d bytes of audio data at a time", (int)bytesToFill); - failed=true; - pa_threaded_mainloop_unlock(mainloop); - return; - } - InvokeCallback(remainingData+remainingDataSize, 960*2); - remainingDataSize+=960*2; - } - memcpy(buffer, remainingData, bytesToFill); - memmove(remainingData, remainingData+bytesToFill, remainingDataSize-bytesToFill); - remainingDataSize-=bytesToFill; + InvokeCallback(remainingData+remainingDataSize, 960*2); + remainingDataSize+=960*2; }else{ - memset(buffer, 0, bytesToFill); + memset(remainingData+remainingDataSize, 0, requestedBytes-remainingDataSize); + remainingDataSize=requestedBytes; } - - err=pa_stream_write(stream, buffer, bytesToFill, NULL, 0LL, PA_SEEK_RELATIVE); - CHECK_ERROR(err, "pa_stream_write"); - - bytesRemaining -= bytesToFill; } + int err=pa_stream_write(stream, remainingData, requestedBytes, NULL, 0, PA_SEEK_RELATIVE); + CHECK_ERROR(err, "pa_stream_write"); + remainingDataSize-=requestedBytes; + if(remainingDataSize>0) + memmove(remainingData, remainingData+requestedBytes, remainingDataSize); } void AudioOutputPulse::StreamSuccessCallback(pa_stream *stream, int success, void *userdata) {