Skip to content

Commit

Permalink
2.2.4
Browse files Browse the repository at this point in the history
- Added tests (using xcode)
- Added a define to enable callback-based audio I/O instead of using actual audio devices
- Fixed a crash on Windows when there's no access to the microphone
- Misc fixes
  • Loading branch information
grishka committed Aug 31, 2018
1 parent 31fe4af commit 64f1458
Show file tree
Hide file tree
Showing 18 changed files with 1,394 additions and 185 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,9 @@ x86/
bld/
[Bb]in/
[Oo]bj/
DerivedData/

# Visual Studio 2015 cache/options directory
.vs/

xcuserdata/
xcuserdata/
4 changes: 3 additions & 1 deletion MediaStreamItf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@ void MediaStreamItf::SetCallback(size_t (*f)(unsigned char *, size_t, void*), vo
}

size_t MediaStreamItf::InvokeCallback(unsigned char *data, size_t length){
return (*callback)(data, length, callbackParam);
if(callback)
return (*callback)(data, length, callbackParam);
return NULL;
}

AudioMixer::AudioMixer() : bufferPool(960*2, 16), processedQueue(16), semaphore(16, 0){
Expand Down
47 changes: 34 additions & 13 deletions VoIPController.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ int64_t VoIPController::win32TimeScale = 0;
bool VoIPController::didInitWin32TimeScale = false;
#endif

#if defined(TGVOIP_USE_CALLBACK_AUDIO_IO)
#include "audio/AudioIOCallback.h"
#endif

#ifndef TGVOIP_USE_CUSTOM_CRYPTO
extern "C" {
#include <openssl/sha.h>
Expand Down Expand Up @@ -2404,8 +2408,8 @@ void VoIPController::SetConfig(const Config& cfg){
#endif
if(statsDump)
fprintf(statsDump, "Time\tRTT\tLRSeq\tLSSeq\tLASeq\tLostR\tLostS\tCWnd\tBitrate\tLoss%%\tJitter\tJDelay\tAJDelay\n");
else
LOGW("Failed to open stats dump file %s for writing", config.statsDumpFilePath.c_str());
//else
// LOGW("Failed to open stats dump file %s for writing", config.statsDumpFilePath.c_str());
}else{
statsDump=NULL;
}
Expand Down Expand Up @@ -2655,17 +2659,11 @@ void VoIPController::StartAudio(){
encoder->SetEchoCanceller(echoCanceller);
encoder->SetSecondaryEncoderEnabled(false);

encoder->Start();
if(!micMuted){
audioInput->Start();
if(!audioInput->IsInitialized()){
LOGE("Erorr initializing audio capture");
lastError=ERROR_AUDIO_IO;

SetState(STATE_FAILED);
return;
}
}
#if defined(TGVOIP_USE_CALLBACK_AUDIO_IO)
dynamic_cast<audio::AudioInputCallback*>(audioInput)->SetDataCallback(audioInputDataCallback);
dynamic_cast<audio::AudioOutputCallback*>(audioOutput)->SetDataCallback(audioOutputDataCallback);
#endif

if(!audioOutput->IsInitialized()){
LOGE("Erorr initializing audio playback");
lastError=ERROR_AUDIO_IO;
Expand All @@ -2690,6 +2688,18 @@ void VoIPController::StartAudio(){
jitterBuffer->SetMinPacketCount((uint32_t) ServerConfig::GetSharedInstance()->GetInt("jitter_initial_delay_20", 6));*/
//audioOutput->Start();
OnAudioOutputReady();

encoder->Start();
if(!micMuted){
audioInput->Start();
if(!audioInput->IsInitialized()){
LOGE("Erorr initializing audio capture");
lastError=ERROR_AUDIO_IO;

SetState(STATE_FAILED);
return;
}
}
}

void VoIPController::OnAudioOutputReady(){
Expand Down Expand Up @@ -2793,6 +2803,17 @@ void VoIPController::ResetEndpointPingStats(){
}
}

#if defined(TGVOIP_USE_CALLBACK_AUDIO_IO)
void VoIPController::SetAudioDataCallbacks(std::function<void(int16_t*, size_t)> input, std::function<void(int16_t*, size_t)> output){
audioInputDataCallback=input;
audioOutputDataCallback=output;
}
#endif

int VoIPController::GetConnectionState(){
return state;
}

#pragma mark - Timer methods

void VoIPController::SendUdpPings(){
Expand Down
12 changes: 11 additions & 1 deletion VoIPController.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
#include "PacketReassembler.h"
#include "MessageThread.h"

#define LIBTGVOIP_VERSION "2.2.3"
#define LIBTGVOIP_VERSION "2.2.4"

#ifdef _WIN32
#undef GetCurrentTime
Expand Down Expand Up @@ -362,6 +362,11 @@ namespace tgvoip{
*/
void RequestCallUpgrade();
void SetEchoCancellationStrength(int strength);
int GetConnectionState();

#if defined(TGVOIP_USE_CALLBACK_AUDIO_IO)
void SetAudioDataCallbacks(std::function<void(int16_t*, size_t)> input, std::function<void(int16_t*, size_t)> output);
#endif

struct Callbacks{
void (*connectionStateChanged)(VoIPController*, int);
Expand Down Expand Up @@ -604,6 +609,11 @@ namespace tgvoip{
uint32_t initTimeoutID=MessageThread::INVALID_ID;
uint32_t noStreamsNopID=MessageThread::INVALID_ID;
uint32_t udpPingTimeoutID=MessageThread::INVALID_ID;

#if defined(TGVOIP_USE_CALLBACK_AUDIO_IO)
std::function<void(int16_t*, size_t)> audioInputDataCallback;
std::function<void(int16_t*, size_t)> audioOutputDataCallback;
#endif

/*** server config values ***/
uint32_t maxAudioBitrate;
Expand Down
8 changes: 6 additions & 2 deletions audio/AudioIO.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@
#include "config.h"
#endif

#if defined(__ANDROID__)
#if defined(TGVOIP_USE_CALLBACK_AUDIO_IO)
#include "AudioIOCallback.h"
#elif defined(__ANDROID__)
#include "../os/android/AudioInputAndroid.h"
#include "../os/android/AudioOutputAndroid.h"
#elif defined(__APPLE__)
Expand Down Expand Up @@ -47,7 +49,9 @@ using namespace std;

shared_ptr<AudioIO> AudioIO::Create(){
std::string inputDevice="default", outputDevice="default";
#if defined(__ANDROID__)
#if defined(TGVOIP_USE_CALLBACK_AUDIO_IO)
return std::make_shared<AudioIOCallback>();
#elif defined(__ANDROID__)
return std::make_shared<ContextlessAudioIO<AudioInputAndroid, AudioOutputAndroid>>();
#elif defined(__APPLE__)
#if TARGET_OS_OSX
Expand Down
3 changes: 3 additions & 0 deletions audio/AudioIO.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,17 @@

#include "AudioInput.h"
#include "AudioOutput.h"
#include "../utils.h"
#include <memory>
#include <string>

namespace tgvoip{
namespace audio {
class AudioIO{
public:
AudioIO(){};
virtual ~AudioIO(){};
TGVOIP_DISALLOW_COPY_AND_ASSIGN(AudioIO);
static std::shared_ptr<AudioIO> Create();
virtual AudioInput* GetInput()=0;
virtual AudioOutput* GetOutput()=0;
Expand Down
121 changes: 121 additions & 0 deletions audio/AudioIOCallback.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
//
// libtgvoip is free and unencumbered public domain software.
// For more information, see http://unlicense.org or the UNLICENSE file
// you should have received with this source code distribution.
//

#include "AudioIOCallback.h"
#include "../VoIPController.h"
#include "../logging.h"

using namespace tgvoip;
using namespace tgvoip::audio;

#pragma mark - IO

AudioIOCallback::AudioIOCallback(){
input=new AudioInputCallback();
output=new AudioOutputCallback();
}

AudioIOCallback::~AudioIOCallback(){
delete input;
delete output;
}

AudioInput* AudioIOCallback::GetInput(){
return input;
}

AudioOutput* AudioIOCallback::GetOutput(){
return output;
}

#pragma mark - Input

AudioInputCallback::AudioInputCallback(){
thread=new Thread(new MethodPointer<AudioInputCallback>(&AudioInputCallback::RunThread, this), NULL);
thread->SetName("AudioInputCallback");
}

AudioInputCallback::~AudioInputCallback(){
running=false;
thread->Join();
delete thread;
}

void AudioInputCallback::Start(){
if(!running){
running=true;
thread->Start();
}
recording=true;
}

void AudioInputCallback::Stop(){
recording=false;
}

void AudioInputCallback::SetDataCallback(std::function<void(int16_t*, size_t)> c){
dataCallback=c;
}

void AudioInputCallback::RunThread(void*){
int16_t buf[960];
while(running){
double t=VoIPController::GetCurrentTime();
memset(buf, 0, sizeof(buf));
dataCallback(buf, 960);
InvokeCallback(reinterpret_cast<unsigned char*>(buf), 960*2);
double sl=0.02-(VoIPController::GetCurrentTime()-t);
if(sl>0)
Thread::Sleep(sl);
}
}

#pragma mark - Output

AudioOutputCallback::AudioOutputCallback(){
thread=new Thread(new MethodPointer<AudioOutputCallback>(&AudioOutputCallback::RunThread, this), NULL);
thread->SetName("AudioOutputCallback");
}

AudioOutputCallback::~AudioOutputCallback(){
running=false;
thread->Join();
delete thread;
}

void AudioOutputCallback::Start(){
if(!running){
running=true;
thread->Start();
}
playing=true;
}

void AudioOutputCallback::Stop(){
playing=false;
}

bool AudioOutputCallback::IsPlaying(){
return playing;
}

void AudioOutputCallback::SetDataCallback(std::function<void(int16_t*, size_t)> c){
dataCallback=c;
}

void AudioOutputCallback::RunThread(void*){
int16_t buf[960];
while(running){
double t=VoIPController::GetCurrentTime();
InvokeCallback(reinterpret_cast<unsigned char*>(buf), 960*2);
dataCallback(buf, 960);
double sl=0.02-(VoIPController::GetCurrentTime()-t);
if(sl>0)
Thread::Sleep(sl);
}
}


62 changes: 62 additions & 0 deletions audio/AudioIOCallback.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
//
// libtgvoip is free and unencumbered public domain software.
// For more information, see http://unlicense.org or the UNLICENSE file
// you should have received with this source code distribution.
//

#ifndef LIBTGVOIP_AUDIO_IO_CALLBACK
#define LIBTGVOIP_AUDIO_IO_CALLBACK

#include <AudioIO.h>
#include <functional>

#include "../threading.h"

namespace tgvoip{
namespace audio{
class AudioInputCallback : public AudioInput{
public:
AudioInputCallback();
virtual ~AudioInputCallback();
virtual void Start() override;
virtual void Stop() override;
void SetDataCallback(std::function<void(int16_t*, size_t)> c);
private:
void RunThread(void*);
bool running=false;
bool recording=false;
Thread* thread;
std::function<void(int16_t*, size_t)> dataCallback;
};

class AudioOutputCallback : public AudioOutput{
public:
AudioOutputCallback();
virtual ~AudioOutputCallback();
virtual void Start() override;
virtual void Stop() override;
virtual bool IsPlaying() override;
void SetDataCallback(std::function<void(int16_t*, size_t)> c);
private:
void RunThread(void*);
bool running=false;
bool playing=false;
Thread* thread;
std::function<void(int16_t*, size_t)> dataCallback;
};

class AudioIOCallback : public AudioIO{
public:
AudioIOCallback();
virtual ~AudioIOCallback();
virtual AudioInput* GetInput() override;
virtual AudioOutput* GetOutput() override;
private:
AudioInputCallback* input;
AudioOutputCallback* output;
};
}
}


#endif /* LIBTGVOIP_AUDIO_IO_CALLBACK */
8 changes: 6 additions & 2 deletions audio/AudioInput.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@
#include "config.h"
#endif

#if defined(__ANDROID__)
#if defined(TGVOIP_USE_CALLBACK_AUDIO_IO)
// nothing
#elif defined(__ANDROID__)
#include "../os/android/AudioInputAndroid.h"
#elif defined(__APPLE__)
#include <TargetConditionals.h>
Expand Down Expand Up @@ -58,7 +60,9 @@ bool AudioInput::IsInitialized(){
}

void AudioInput::EnumerateDevices(std::vector<AudioInputDevice>& devs){
#if defined(__APPLE__) && TARGET_OS_OSX
#if defined(TGVOIP_USE_CALLBACK_AUDIO_IO)
// not supported
#elif defined(__APPLE__) && TARGET_OS_OSX
AudioInputAudioUnitLegacy::EnumerateDevices(devs);
#elif defined(_WIN32)
#ifdef TGVOIP_WINXP_COMPAT
Expand Down
Loading

0 comments on commit 64f1458

Please sign in to comment.