Merge branch 'master' into multichannel

Resolved Conflicts:
	daemon/src/audio/alsa/alsalayer.cpp
	daemon/src/audio/audioloop.cpp
	daemon/src/audio/audiortp/audio_rtp_record_handler.cpp
	daemon/src/audio/codecs/alaw.cpp
	daemon/src/audio/codecs/audiocodecfactory.cpp
	daemon/src/audio/codecs/g722.cpp
	daemon/src/audio/codecs/gsmcodec.cpp
	daemon/src/audio/codecs/ulaw.cpp
	daemon/src/audio/dcblocker.cpp
	daemon/src/audio/mainbuffer.cpp
	daemon/src/audio/pulseaudio/audiostream.cpp
	daemon/src/audio/pulseaudio/pulselayer.cpp
	daemon/src/audio/ringbuffer.cpp
	daemon/src/audio/samplerateconverter.cpp
	daemon/src/audio/sound/audiofile.cpp
This commit is contained in:
Tristan Matthews
2013-07-09 14:11:10 -04:00
24 changed files with 369 additions and 268 deletions

View File

@ -42,7 +42,7 @@
#define SFL_ALSA_PERIOD_SIZE 160
#define SFL_ALSA_NB_PERIOD 8
#define SFL_ALSA_BUFFER_SIZE SFL_ALSA_PERIOD_SIZE*SFL_ALSA_NB_PERIOD
#define SFL_ALSA_BUFFER_SIZE SFL_ALSA_PERIOD_SIZE * SFL_ALSA_NB_PERIOD
class AlsaThread {
public:
@ -74,6 +74,7 @@ bool AlsaThread::isRunning() const
AlsaThread::~AlsaThread()
{
running_ = false;
if (thread_)
pthread_join(thread_, NULL);
}
@ -149,7 +150,6 @@ void AlsaThread::run()
}
}
// Constructor
AlsaLayer::AlsaLayer(const AudioPreference &pref)
: indexIn_(pref.getAlsaCardin())
, indexOut_(pref.getAlsaCardout())
@ -172,7 +172,6 @@ AlsaLayer::AlsaLayer(const AudioPreference &pref)
setPlaybackGain(pref.getVolumespkr());
}
// Destructor
AlsaLayer::~AlsaLayer()
{
isStarted_ = false;
@ -198,7 +197,7 @@ bool AlsaLayer::openDevice(snd_pcm_t **pcm, const std::string &dev, snd_pcm_stre
if (err < 0) {
ERROR("Alsa: couldn't open device %s : %s", dev.c_str(),
snd_strerror(err));
snd_strerror(err));
return false;
}
@ -248,10 +247,6 @@ AlsaLayer::stopStream()
flushMain();
}
//////////////////////////////////////////////////////////////////////////////////////////////
///////////////// ALSA PRIVATE FUNCTIONS ////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////
/*
* GCC extension : statement expression
*
@ -388,11 +383,12 @@ bool AlsaLayer::alsa_set_params(snd_pcm_t *pcm_handle)
ERROR("buffer to small, could not use");
return false;
}
#undef HW
DEBUG("%s using sampling rate %dHz",
(snd_pcm_stream(pcm_handle) == SND_PCM_STREAM_PLAYBACK) ? "playback" : "capture",
sampleRate_);
(snd_pcm_stream(pcm_handle) == SND_PCM_STREAM_PLAYBACK) ? "playback" : "capture",
sampleRate_);
snd_pcm_sw_params_t *swparams = NULL;
snd_pcm_sw_params_alloca(&swparams);
@ -408,13 +404,14 @@ bool AlsaLayer::alsa_set_params(snd_pcm_t *pcm_handle)
#undef TRY
}
//TODO first frame causes broken pipe (underrun) because not enough data are send --> make the handle wait to be ready
// TODO first frame causes broken pipe (underrun) because not enough data is sent
// we should wait until the handle is ready
void
AlsaLayer::write(void* buffer, int length, snd_pcm_t * handle)
{
//Do not waste CPU cycle to handle void
// Skip empty buffers
if (!length)
return;
return;
snd_pcm_uframes_t frames = snd_pcm_bytes_to_frames(handle, length);
watchdogTotalCount_++;
@ -454,12 +451,14 @@ AlsaLayer::write(void* buffer, int length, snd_pcm_t * handle)
ERROR("Writing in state SND_PCM_STATE_SETUP, should be "
"SND_PCM_STATE_PREPARED or SND_PCM_STATE_RUNNING");
int error = snd_pcm_prepare(handle);
if (error < 0) {
ERROR("Failed to prepare handle: %s", snd_strerror(error));
stopPlaybackStream();
}
}
}
break;
}
@ -469,8 +468,9 @@ AlsaLayer::write(void* buffer, int length, snd_pcm_t * handle)
break;
}
//Detect when something is going wrong. This can be caused by alsa bugs or faulty encoder on the other side
//TODO do something useful instead of just warning and flushing buffers
// Detect when something is going wrong. This can be caused by alsa bugs or
// faulty encoder on the other side
// TODO do something useful instead of just warning and flushing buffers
if (watchdogTotalErr_ > 0 && watchdogTotalCount_ / watchdogTotalErr_ >=4 && watchdogTotalCount_ > 50) {
ERROR("Alsa: too many errors (%d error on %d frame)",watchdogTotalErr_,watchdogTotalCount_);
flushUrgent();
@ -539,13 +539,16 @@ namespace {
bool safeUpdate(snd_pcm_t *handle, int &samples)
{
samples = snd_pcm_avail_update(handle);
if (samples < 0) {
samples = snd_pcm_recover(handle, samples, 0);
if (samples < 0) {
ERROR("Got unrecoverable error from snd_pcm_avail_update: %s", snd_strerror(samples));
return false;
}
}
return true;
}
@ -553,9 +556,11 @@ std::vector<std::string>
getValues(const std::vector<HwIDPair> &deviceMap)
{
std::vector<std::string> audioDeviceList;
for (std::vector<HwIDPair>::const_iterator iter = deviceMap.begin();
iter != deviceMap.end(); ++iter)
audioDeviceList.push_back(iter->second);
return audioDeviceList;
}
}
@ -600,12 +605,11 @@ AlsaLayer::getAudioDeviceIndexMap(bool getCapture) const
if (snd_ctl_pcm_info(handle ,pcminfo) < 0) {
DEBUG(" Cannot get info");
}
else {
} else {
DEBUG("card %i : %s [%s]",
numCard,
snd_ctl_card_info_get_id(info),
snd_ctl_card_info_get_name(info));
numCard,
snd_ctl_card_info_get_id(info),
snd_ctl_card_info_get_name(info));
std::string description = snd_ctl_card_info_get_name(info);
description.append(" - ");
description.append(snd_pcm_info_get_name(pcminfo));
@ -635,6 +639,7 @@ AlsaLayer::soundCardIndexExists(int card, PCMType stream)
name.append(ss.str());
snd_ctl_t* handle;
if (snd_ctl_open(&handle, name.c_str(), 0) != 0)
return false;
@ -672,8 +677,10 @@ AlsaLayer::getAudioDeviceName(int index, PCMType type) const
case SFL_PCM_PLAYBACK:
case SFL_PCM_RINGTONE:
return getPlaybackDeviceList().at(index);
case SFL_PCM_CAPTURE:
return getCaptureDeviceList().at(index);
default:
ERROR("Unexpected type %d", type);
return "";
@ -701,6 +708,7 @@ void AlsaLayer::capture()
// TODO: handle ALSA multichannel capture
const int toGetBytes = in.samples() * sizeof(SFLAudioSample);
SFLAudioSample * const in_ptr = &(*in.getChannel()->begin());
if (read(in_ptr, toGetBytes) != toGetBytes) {
ERROR("ALSA MIC : Couldn't read!");
return;
@ -725,6 +733,7 @@ void AlsaLayer::playback(int maxSamples)
size_t bytesToGet = Manager::instance().getMainBuffer().availableForGet(MainBuffer::DEFAULT_ID);
const size_t bytesToPut = maxSamples * sizeof(SFLAudioSample);
// no audio available, play tone or silence
if (bytesToGet <= 0) {
// FIXME: not thread safe! we only lock the mutex when we get the
@ -733,6 +742,7 @@ void AlsaLayer::playback(int maxSamples)
AudioLoop *file_tone = Manager::instance().getTelephoneFile();
AudioBuffer out(maxSamples, 1, sampleRate_);
if (tone)
tone->getNext(out, getPlaybackGain());
else if (file_tone && !ringtoneHandle_)
@ -747,6 +757,7 @@ void AlsaLayer::playback(int maxSamples)
double resampleFactor = 1.0;
size_t maxNbBytesToGet = bytesToPut;
if (resample) {
resampleFactor = static_cast<double>(sampleRate_) / mainBufferSampleRate;
maxNbBytesToGet = bytesToGet / resampleFactor;
@ -788,6 +799,7 @@ void AlsaLayer::audioCallback()
snd_pcm_wait(playbackHandle_, 20);
int playbackAvailSmpl = 0;
if (not safeUpdate(playbackHandle_, playbackAvailSmpl))
return;
@ -811,6 +823,7 @@ void AlsaLayer::audioCallback()
if (ringtoneHandle_) {
AudioLoop *file_tone = Manager::instance().getTelephoneFile();
int ringtoneAvailSmpl = 0;
if (not safeUpdate(ringtoneHandle_, ringtoneAvailSmpl))
return;
int ringtoneAvailBytes = ringtoneAvailSmpl * sizeof(SFLAudioSample);
@ -836,12 +849,15 @@ void AlsaLayer::updatePreference(AudioPreference &preference, int index, PCMType
case SFL_PCM_PLAYBACK:
preference.setAlsaCardout(index);
break;
case AudioLayer::SFL_PCM_CAPTURE:
preference.setAlsaCardin(index);
break;
case AudioLayer::SFL_PCM_RINGTONE:
preference.setAlsaCardring(index);
break;
default:
break;
}

View File

@ -100,16 +100,17 @@ AudioLoop::getNext(AudioBuffer& output, unsigned int volume)
// We want to send values in milisecond
int divisor = buffer_->getSampleRate() / 1000;
if(divisor == 0) {
if (divisor == 0) {
ERROR("Error cannot update playback slider, sampling rate is 0");
return;
}
if(isRecording_) {
if((updatePlaybackScale % 5) == 0) {
if (isRecording_) {
if ((updatePlaybackScale % 5) == 0) {
CallManager *cm = Manager::instance().getClient()->getCallManager();
cm->updatePlaybackScale(pos_ / divisor, buf_samples / divisor);
}
updatePlaybackScale++;
}
}

View File

@ -149,7 +149,7 @@ namespace {
bool
nonFilenameCharacter(char c)
{
return not (std::isalnum(c) or c == '_' or c == '.');
return not(std::isalnum(c) or c == '_' or c == '.');
}
// Replace any character that is inappropriate for a filename with '_'
@ -200,6 +200,7 @@ bool AudioRecord::openFile()
result = setWavFile();
} else {
DEBUG("Filename already exists, opening it");
if (fileType_ == FILE_RAW)
result = openExistingRawFile();
else if (fileType_ == FILE_WAV)
@ -242,6 +243,7 @@ bool AudioRecord::toggleRecording()
openFile();
recordingEnabled_ = true;
}
return recordingEnabled_;
}
@ -266,24 +268,24 @@ bool AudioRecord::setRawFile()
}
namespace {
std::string header_to_string(const wavhdr &hdr)
{
std::stringstream ss;
ss << hdr.riff << "\0 "
<< hdr.file_size << " "
<< hdr.wave << "\0 "
<< hdr.fmt << "\0 "
<< hdr.chunk_size << " "
<< hdr.format_tag << " "
<< hdr.num_chans << " "
<< hdr.sample_rate << " "
<< hdr.bytes_per_sec << " "
<< hdr.bytes_per_samp << " "
<< hdr.bits_per_samp << " "
<< hdr.data << "\0 "
<< hdr.data_length;
return ss.str();
}
std::string header_to_string(const wavhdr &hdr)
{
std::stringstream ss;
ss << hdr.riff << "\0 "
<< hdr.file_size << " "
<< hdr.wave << "\0 "
<< hdr.fmt << "\0 "
<< hdr.chunk_size << " "
<< hdr.format_tag << " "
<< hdr.num_chans << " "
<< hdr.sample_rate << " "
<< hdr.bytes_per_sec << " "
<< hdr.bytes_per_samp << " "
<< hdr.bits_per_samp << " "
<< hdr.data << "\0 "
<< hdr.data_length;
return ss.str();
}
}
bool AudioRecord::setWavFile()
@ -301,18 +303,19 @@ bool AudioRecord::setWavFile()
* write them as arrays since strings enclosed in quotes include a
* null character */
wavhdr hdr = {{'R', 'I', 'F', 'F'},
44,
{'W', 'A', 'V', 'E'},
{'f','m', 't', ' '},
16,
1,
channels_,
sndSmplRate_,
-1, /* initialized below */
-1, /* initialized below */
16,
{'d', 'a', 't', 'a'},
0};
44,
{'W', 'A', 'V', 'E'},
{'f','m', 't', ' '},
16,
1,
channels_,
sndSmplRate_,
-1, /* initialized below */
-1, /* initialized below */
16,
{'d', 'a', 't', 'a'},
0
};
hdr.bytes_per_samp = channels_ * hdr.bits_per_samp / 8;
hdr.bytes_per_sec = hdr.sample_rate * hdr.bytes_per_samp;

View File

@ -56,8 +56,10 @@ AudioRecorder::AudioRecorder(AudioRecord *arec, MainBuffer *mb) :
recorderId_ = id.append(s);
}
AudioRecorder::~AudioRecorder() {
AudioRecorder::~AudioRecorder()
{
running_ = false;
if (thread_)
pthread_join(thread_, NULL);
}

View File

@ -68,6 +68,7 @@ AudioRtpFactory::~AudioRtpFactory()
void AudioRtpFactory::initConfig()
{
DEBUG("AudioRtpFactory: init config");
if (rtpSession_ != NULL)
stop();
@ -78,18 +79,22 @@ void AudioRtpFactory::initConfig()
if (account) {
srtpEnabled_ = account->getSrtpEnabled();
std::string key(account->getSrtpKeyExchange());
if (srtpEnabled_) {
#if HAVE_ZRTP
if (key == "sdes")
keyExchangeProtocol_ = SDES;
else if (key == "zrtp")
keyExchangeProtocol_ = ZRTP;
#else
keyExchangeProtocol_ = SDES;
keyExchangeProtocol_ = SDES;
#endif
} else {
keyExchangeProtocol_ = NONE;
}
helloHashEnabled_ = account->getZrtpHelloHash();
} else {
srtpEnabled_ = false;
@ -107,14 +112,18 @@ void AudioRtpFactory::initSession()
switch (keyExchangeProtocol_) {
#if HAVE_ZRTP
case ZRTP:
rtpSession_ = new AudioZrtpSession(*ca_, zidFilename);
// TODO: be careful with that. The hello hash is computed asynchronously. Maybe it's
// not even available at that point.
if (helloHashEnabled_)
ca_->getLocalSDP()->setZrtpHash(static_cast<AudioZrtpSession *>(rtpSession_)->getHelloHash());
break;
#endif
case SDES:
rtpSession_ = new AudioSrtpSession(*ca_);
break;
@ -192,6 +201,7 @@ AudioZrtpSession * AudioRtpFactory::getAudioZrtpSession()
void AudioRtpFactory::initLocalCryptoInfo()
{
DEBUG("AudioRtpFactory: Init local crypto info");
if (rtpSession_ && keyExchangeProtocol_ == SDES) {
AudioSrtpSession *srtp = static_cast<AudioSrtpSession*>(rtpSession_);
// the context is invalidated and deleted by the call to initLocalCryptoInfo
@ -203,6 +213,7 @@ void AudioRtpFactory::initLocalCryptoInfo()
void AudioRtpFactory::initLocalCryptoInfoOnOffHold()
{
DEBUG("AudioRtpFactory: Init local crypto info");
if (rtpSession_ && keyExchangeProtocol_ == SDES) {
AudioSrtpSession *srtp = static_cast<AudioSrtpSession*>(rtpSession_);
// the context is invalidated and deleted by the call to initLocalCryptoInfo
@ -214,7 +225,7 @@ void AudioRtpFactory::initLocalCryptoInfoOnOffHold()
void AudioRtpFactory::setRemoteCryptoInfo(SdesNegotiator& nego)
{
if (rtpSession_ ) {
if (rtpSession_) {
if (keyExchangeProtocol_ == SDES) {
AudioSrtpSession *srtp = static_cast<AudioSrtpSession *>(rtpSession_);
srtp->setRemoteCryptoInfo(nego);

View File

@ -44,37 +44,41 @@
namespace sfl {
#ifdef RECTODISK
std::ofstream rtpResampled ("testRtpOutputResampled.raw", std::ifstream::binary);
std::ofstream rtpResampled("testRtpOutputResampled.raw", std::ifstream::binary);
std::ofstream rtpNotResampled("testRtpOutput.raw", std::ifstream::binary);
#endif
DTMFEvent::DTMFEvent(char digit) : payload(), newevent(true), length(1000)
{
/*
From RFC2833:
/*
From RFC2833:
Event encoding (decimal)
_________________________
0--9 0--9
* 10
# 11
A--D 12--15
Flash 16
*/
Event encoding (decimal)
_________________________
0--9 0--9
* 10
# 11
A--D 12--15
Flash 16
*/
switch (digit) {
case '*':
digit = 10;
break;
case '#':
digit = 11;
break;
case 'A' ... 'D':
digit = digit - 'A' + 12;
break;
case '0' ... '9':
digit = digit - '0';
break;
default:
ERROR("Unexpected DTMF %c", digit);
}
@ -86,7 +90,7 @@ DTMFEvent::DTMFEvent(char digit) : payload(), newevent(true), length(1000)
}
AudioRtpRecord::AudioRtpRecord() :
callId_("")
callId_("")
, codecSampleRate_(0)
, dtmfQueue_()
, audioCodecs_()
@ -134,6 +138,7 @@ AudioRtpRecord::getCurrentCodec() const
ERROR("No codec found");
return 0;
}
return audioCodecs_[currentCodecIndex_];
}
@ -142,6 +147,7 @@ AudioRtpRecord::deleteCodecs()
{
for (std::vector<AudioCodec *>::iterator i = audioCodecs_.begin(); i != audioCodecs_.end(); ++i)
delete *i;
audioCodecs_.clear();
}
@ -212,10 +218,12 @@ AudioRtpRecordHandler::getCurrentAudioCodecNames()
ScopedLock lock(audioRtpRecord_.audioCodecMutex_);
{
std::string sep = "";
for (std::vector<AudioCodec*>::const_iterator i = audioRtpRecord_.audioCodecs_.begin();
i != audioRtpRecord_.audioCodecs_.end(); ++i) {
if (*i)
result += sep + (*i)->getMimeSubtype();
sep = " ";
}
}
@ -230,6 +238,7 @@ void AudioRtpRecordHandler::setRtpMedia(const std::vector<AudioCodec*> &audioCod
audioRtpRecord_.deleteCodecs();
// Set various codec info to reduce indirection
audioRtpRecord_.audioCodecs_ = audioCodecs;
if (audioCodecs.empty()) {
ERROR("Audio codecs empty");
return;
@ -320,11 +329,13 @@ int AudioRtpRecordHandler::processDataEncode()
}
#if HAVE_SPEEXDSP
if (Manager::instance().audioPreference.getNoiseReduce()) {
ScopedLock lock(audioRtpRecord_.audioProcessMutex_);
RETURN_IF_NULL(audioRtpRecord_.noiseSuppressEncode_, 0, "Noise suppressor already destroyed");
audioRtpRecord_.noiseSuppressEncode_->process(micData, getCodecFrameSize());
}
#endif
{ ScopedLock lock(audioRtpRecord_.audioCodecMutex_);
@ -341,13 +352,16 @@ void AudioRtpRecordHandler::processDataDecode(unsigned char *spkrData, size_t si
{
if (audioRtpRecord_.isDead())
return;
if (audioRtpRecord_.decoderPayloadType_ != payloadType) {
const bool switched = audioRtpRecord_.tryToSwitchPayloadTypes(payloadType);
if (not switched) {
if (!warningInterval_) {
warningInterval_ = 250;
WARN("Invalid payload type %d, expected %d", payloadType, audioRtpRecord_.decoderPayloadType_);
}
warningInterval_--;
return;
}
@ -363,11 +377,13 @@ void AudioRtpRecordHandler::processDataDecode(unsigned char *spkrData, size_t si
}
#if HAVE_SPEEXDSP
if (Manager::instance().audioPreference.getNoiseReduce()) {
ScopedLock lock(audioRtpRecord_.audioProcessMutex_);
RETURN_IF_NULL(audioRtpRecord_.noiseSuppressDecode_, "Noise suppressor already destroyed");
audioRtpRecord_.noiseSuppressDecode_->process(audioRtpRecord_.decData_, getCodecFrameSize());
}
#endif
audioRtpRecord_.fadeInDecodedData();
@ -410,17 +426,22 @@ bool
AudioRtpRecordHandler::codecsDiffer(const std::vector<AudioCodec*> &codecs) const
{
const std::vector<AudioCodec*> &current = audioRtpRecord_.audioCodecs_;
if (codecs.size() != current.size())
return true;
for (std::vector<AudioCodec*>::const_iterator i = codecs.begin(); i != codecs.end(); ++i) {
if (*i) {
bool matched = false;
for (std::vector<AudioCodec*>::const_iterator j = current.begin(); !matched and j != current.end(); ++j)
matched = (*i)->getPayloadType() == (*j)->getPayloadType();
if (not matched)
return true;
}
}
return false;
}

View File

@ -71,11 +71,13 @@ void AudioRtpSession::updateSessionMedia(const std::vector<AudioCodec*> &audioCo
Manager::instance().audioSamplingRateChanged(audioRtpRecord_.codecSampleRate_);
#if HAVE_SPEEXDSP
if (lastSamplingRate != audioRtpRecord_.codecSampleRate_) {
DEBUG("Update noise suppressor with sampling rate %d and frame size %d",
getCodecSampleRate(), getCodecFrameSize());
initNoiseSuppress();
}
#endif
}
@ -85,6 +87,7 @@ void AudioRtpSession::setSessionMedia(const std::vector<AudioCodec*> &audioCodec
// G722 requires timestamp to be incremented at 8kHz
const ost::PayloadType payloadType = getEncoderPayloadType();
if (payloadType == ost::sptG722) {
const int G722_RTP_TIME_INCREMENT = 160;
timestampIncrement_ = G722_RTP_TIME_INCREMENT;
@ -93,7 +96,7 @@ void AudioRtpSession::setSessionMedia(const std::vector<AudioCodec*> &audioCodec
if (payloadType == ost::sptG722) {
const int G722_RTP_CLOCK_RATE = 8000;
queue_.setPayloadFormat(ost::DynamicPayloadFormat( payloadType, G722_RTP_CLOCK_RATE));
queue_.setPayloadFormat(ost::DynamicPayloadFormat(payloadType, G722_RTP_CLOCK_RATE));
} else {
if (getHasDynamicPayload())
queue_.setPayloadFormat(ost::DynamicPayloadFormat(payloadType, getCodecSampleRate()));
@ -125,7 +128,8 @@ void AudioRtpSession::sendDtmfEvent()
// Set marker in case this is a new Event
if (dtmf.newevent)
queue_.setMark(true);
queue_.sendImmediate(timestamp_, (const unsigned char *) (& (dtmf.payload)), sizeof (ost::RTPPacket::RFC2833Payload));
queue_.sendImmediate(timestamp_, (const unsigned char *)(& (dtmf.payload)), sizeof(ost::RTPPacket::RFC2833Payload));
// This is no longer a new event
if (dtmf.newevent) {
@ -140,9 +144,11 @@ void AudioRtpSession::sendDtmfEvent()
// decrease length remaining to process for this event
dtmf.length -= increment;
dtmf.payload.duration++;
// next packet is going to be the last one
if ((dtmf.length - increment) < increment)
dtmf.payload.ebit = true;
if (dtmf.length < increment)
audioRtpRecord_.dtmfQueue_.pop_front();
}
@ -200,7 +206,7 @@ void AudioRtpSession::setDestinationIpAddress()
if (!remote_ip_) {
WARN("Target IP address (%s) is not correct!",
call_.getLocalSDP()->getRemoteIP().data());
call_.getLocalSDP()->getRemoteIP().data());
return;
}
@ -276,6 +282,7 @@ AudioRtpSession::AudioRtpSendThread::AudioRtpSendThread(AudioRtpSession &session
AudioRtpSession::AudioRtpSendThread::~AudioRtpSendThread()
{
running_ = false;
if (thread_)
pthread_join(thread_, NULL);
}

View File

@ -47,84 +47,84 @@
namespace sfl {
namespace {
std::string
encodeBase64(unsigned char *input, int length)
{
// init decoder
BIO *b64 = BIO_new(BIO_f_base64());
BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
std::string
encodeBase64(unsigned char *input, int length)
{
// init decoder
BIO *b64 = BIO_new(BIO_f_base64());
BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
// init internal buffer
BIO *bmem = BIO_new(BIO_s_mem());
// init internal buffer
BIO *bmem = BIO_new(BIO_s_mem());
// create decoder chain
b64 = BIO_push(b64, bmem);
// create decoder chain
b64 = BIO_push(b64, bmem);
BIO_write(b64, input, length);
// BIO_flush (b64);
BIO_write(b64, input, length);
// BIO_flush (b64);
// get pointer to data
BUF_MEM *bptr = 0;
BIO_get_mem_ptr(b64, &bptr);
// get pointer to data
BUF_MEM *bptr = 0;
BIO_get_mem_ptr(b64, &bptr);
std::string output(bptr->data, bptr->length);
std::string output(bptr->data, bptr->length);
BIO_free_all(bmem);
BIO_free_all(bmem);
return output;
}
return output;
}
std::vector<char> decodeBase64(unsigned char *input, int length)
{
BIO *b64, *bmem;
std::vector<char> decodeBase64(unsigned char *input, int length)
{
BIO *b64, *bmem;
// init decoder and read-only BIO buffer
b64 = BIO_new(BIO_f_base64());
BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
// init decoder and read-only BIO buffer
b64 = BIO_new(BIO_f_base64());
BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
// init internal buffer
bmem = BIO_new_mem_buf(input, length);
// init internal buffer
bmem = BIO_new_mem_buf(input, length);
// create encoder chain
bmem = BIO_push(b64, bmem);
// create encoder chain
bmem = BIO_push(b64, bmem);
std::vector<char> buffer(length, 0);
BIO_read(bmem, &(*buffer.begin()), length);
std::vector<char> buffer(length, 0);
BIO_read(bmem, &(*buffer.begin()), length);
BIO_free_all(bmem);
BIO_free_all(bmem);
return buffer;
}
return buffer;
}
// Fills the array dest with length random bytes
void bufferFillMasterKey(std::vector<uint8>& dest)
{
DEBUG("Init local master key");
// Fills the array dest with length random bytes
void bufferFillMasterKey(std::vector<uint8>& dest)
{
DEBUG("Init local master key");
// Allocate memory for key
std::vector<unsigned char> random_key(dest.size());
// Allocate memory for key
std::vector<unsigned char> random_key(dest.size());
// Generate ryptographically strong pseudo-random bytes
if (RAND_bytes(&(*random_key.begin()), dest.size()) != 1)
DEBUG("Error occured while generating cryptographically strong pseudo-random key");
// Generate ryptographically strong pseudo-random bytes
if (RAND_bytes(&(*random_key.begin()), dest.size()) != 1)
DEBUG("Error occured while generating cryptographically strong pseudo-random key");
std::copy(random_key.begin(), random_key.end(), dest.begin());
}
std::copy(random_key.begin(), random_key.end(), dest.begin());
}
// Fills the array dest with length random bytes
void bufferFillMasterSalt(std::vector<uint8>& dest)
{
DEBUG("Init local master key");
// Fills the array dest with length random bytes
void bufferFillMasterSalt(std::vector<uint8>& dest)
{
DEBUG("Init local master key");
// Allocate memory for key
std::vector<unsigned char> random_key(dest.size());
// Allocate memory for key
std::vector<unsigned char> random_key(dest.size());
// Generate ryptographically strong pseudo-random bytes
if (RAND_bytes(&(*random_key.begin()), dest.size()) != 1)
DEBUG("Error occured while generating cryptographically strong pseudo-random key");
// Generate ryptographically strong pseudo-random bytes
if (RAND_bytes(&(*random_key.begin()), dest.size()) != 1)
DEBUG("Error occured while generating cryptographically strong pseudo-random key");
std::copy(random_key.begin(), random_key.end(), dest.begin());
}
std::copy(random_key.begin(), random_key.end(), dest.begin());
}
}
AudioSrtpSession::AudioSrtpSession(SIPCall &call) :
@ -213,6 +213,7 @@ void AudioSrtpSession::setRemoteCryptoInfo(const sfl::SdesNegotiator& nego)
// init crypto content in Srtp session
initializeRemoteCryptoContext();
if (remoteCryptoCtx_) {
setInQueueCryptoContext(remoteCryptoCtx_);
}
@ -222,7 +223,7 @@ void AudioSrtpSession::setRemoteCryptoInfo(const sfl::SdesNegotiator& nego)
}
namespace {
static const size_t BITS_PER_BYTE = 8;
static const size_t BITS_PER_BYTE = 8;
}
void AudioSrtpSession::initializeLocalMasterKey()
@ -277,18 +278,18 @@ void AudioSrtpSession::initializeRemoteCryptoContext()
const CryptoSuiteDefinition &crypto = sfl::CryptoSuites[remoteCryptoSuite_];
remoteCryptoCtx_ = new ost::CryptoContext(0x0,
0, // roc,
0L, // keydr,
SrtpEncryptionAESCM,
SrtpAuthenticationSha1Hmac,
&(*remoteMasterKey_.begin()),
remoteMasterKey_.size(),
&(*remoteMasterSalt_.begin()),
remoteMasterSalt_.size(),
crypto.encryptionKeyLength / BITS_PER_BYTE,
crypto.srtpAuthKeyLength / BITS_PER_BYTE,
crypto.masterSaltLength / BITS_PER_BYTE,
crypto.srtpAuthTagLength / BITS_PER_BYTE);
0, // roc,
0L, // keydr,
SrtpEncryptionAESCM,
SrtpAuthenticationSha1Hmac,
&(*remoteMasterKey_.begin()),
remoteMasterKey_.size(),
&(*remoteMasterSalt_.begin()),
remoteMasterSalt_.size(),
crypto.encryptionKeyLength / BITS_PER_BYTE,
crypto.srtpAuthKeyLength / BITS_PER_BYTE,
crypto.masterSaltLength / BITS_PER_BYTE,
crypto.srtpAuthTagLength / BITS_PER_BYTE);
}
@ -299,18 +300,18 @@ void AudioSrtpSession::initializeLocalCryptoContext()
const CryptoSuiteDefinition &crypto = sfl::CryptoSuites[localCryptoSuite_];
localCryptoCtx_ = new ost::CryptoContext(OutgoingDataQueue::getLocalSSRC(),
0, // roc,
0L, // keydr,
SrtpEncryptionAESCM,
SrtpAuthenticationSha1Hmac,
&(*localMasterKey_.begin()),
localMasterKey_.size(),
&(*localMasterSalt_.begin()),
localMasterSalt_.size(),
crypto.encryptionKeyLength / BITS_PER_BYTE,
crypto.srtpAuthKeyLength / BITS_PER_BYTE,
crypto.masterSaltLength / BITS_PER_BYTE,
crypto.srtpAuthTagLength / BITS_PER_BYTE);
0, // roc,
0L, // keydr,
SrtpEncryptionAESCM,
SrtpAuthenticationSha1Hmac,
&(*localMasterKey_.begin()),
localMasterKey_.size(),
&(*localMasterSalt_.begin()),
localMasterSalt_.size(),
crypto.encryptionKeyLength / BITS_PER_BYTE,
crypto.srtpAuthKeyLength / BITS_PER_BYTE,
crypto.masterSaltLength / BITS_PER_BYTE,
crypto.srtpAuthTagLength / BITS_PER_BYTE);
}
void

View File

@ -43,7 +43,7 @@ AudioSymmetricRtpSession::AudioSymmetricRtpSession(SIPCall &call) :
, AudioRtpSession(call, *this)
{
DEBUG("Setting new RTP session with destination %s:%d",
call_.getLocalIp().c_str(), call_.getLocalAudioPort());
call_.getLocalIp().c_str(), call_.getLocalAudioPort());
audioRtpRecord_.callId_ = call_.getCallId();
}

View File

@ -151,12 +151,14 @@ ZrtpSessionCallback::zrtpNegotiationFailed(MessageSeverity severity, int subCode
DEBUG("Sent error packet: ");
std::map<int32, std::string>::const_iterator iter = zrtpMap_.find(subCode);
if (iter != zrtpMap_.end()) {
DEBUG("%s", iter->second.c_str());
Manager::instance().getClient()->getCallManager()->zrtpNegotiationFailed(call_.getCallId(), iter->second, "ZRTP");
}
} else {
std::map<int32, std::string>::const_iterator iter = severeMap_.find(subCode);
if (iter != severeMap_.end()) {
DEBUG("%s", iter->second.c_str());
Manager::instance().getClient()->getCallManager()->zrtpNegotiationFailed(call_.getCallId(), iter->second, "severe");

View File

@ -67,6 +67,7 @@ void
AudioCodecFactory::setDefaultOrder()
{
defaultCodecList_.clear();
for (AudioCodecsMap::const_iterator i = codecsMap_.begin(); i != codecsMap_.end(); ++i)
defaultCodecList_.push_back(i->first);
}
@ -86,6 +87,7 @@ std::vector<int32_t>
AudioCodecFactory::getCodecList() const
{
std::vector<int32_t> list;
for (AudioCodecsMap::const_iterator iter = codecsMap_.begin(); iter != codecsMap_.end(); ++iter)
if (iter->second)
list.push_back((int32_t) iter->first);
@ -159,7 +161,7 @@ AudioCodecFactory::saveActiveCodecs(const std::vector<std::string>& list)
AudioCodecFactory::~AudioCodecFactory()
{
for (std::vector<AudioCodecHandlePointer>::iterator iter =
codecInMemory_.begin(); iter != codecInMemory_.end(); ++iter)
codecInMemory_.begin(); iter != codecInMemory_.end(); ++iter)
unloadCodec(*iter);
}
@ -237,6 +239,7 @@ AudioCodecFactory::loadCodec(const std::string &path)
}
sfl::AudioCodec *a = static_cast<sfl::AudioCodec *>(createCodec());
if (a)
codecInMemory_.push_back(AudioCodecHandlePointer(a, codecHandle));
else
@ -250,6 +253,7 @@ void
AudioCodecFactory::unloadCodec(AudioCodecHandlePointer &ptr)
{
destroy_t *destroyCodec = 0;
if (ptr.second)
destroyCodec = (destroy_t*) dlsym(ptr.second, "destroy");
@ -273,6 +277,7 @@ AudioCodecFactory::instantiateCodec(int payload) const
std::vector<AudioCodecHandlePointer>::const_iterator iter;
sfl::AudioCodec *result = NULL;
for (iter = codecInMemory_.begin(); iter != codecInMemory_.end(); ++iter) {
if (iter->first->getPayloadType() == payload) {
create_t* createCodec = (create_t*) dlsym(iter->second , AUDIO_CODEC_ENTRY_SYMBOL);
@ -308,26 +313,27 @@ AudioCodecFactory::seemsValid(const std::string &lib)
return false;
static const std::string validCodecs[] = {
"ulaw",
"alaw",
"g722",
"g729", //G729 have to be loaded first, if it is valid or not is checked later
"opus", //Opus have to be loaded first, if it is valid or not is checked later
"opus_stereo",
"ulaw",
"alaw",
"g722",
"g729", //G729 have to be loaded first, if it is valid or not is checked later
"opus", //Opus have to be loaded first, if it is valid or not is checked later
"opus_stereo",
#ifdef HAVE_SPEEX_CODEC
"speex_nb",
"speex_wb",
"speex_ub",
"speex_nb",
"speex_wb",
"speex_ub",
#endif
#ifdef HAVE_GSM_CODEC
"gsm",
"gsm",
#endif
#ifdef BUILD_ILBC
"ilbc",
"ilbc",
#endif
""};
""
};
const std::string name(lib.substr(prefix.length(), len));
const std::string *end = validCodecs + ARRAYSIZE(validCodecs);

View File

@ -41,7 +41,7 @@ class G722 : public sfl::AudioCodec {
public:
G722() : sfl::AudioCodec(9, "G722", 16000, 320, 1), decode_state_(),
encode_state_() {
encode_state_() {
bitrate_ = 64;
hasDynamicPayload_ = false;
@ -61,8 +61,7 @@ class G722 : public sfl::AudioCodec {
return out;
}
static void g722_state_init(g722_state_t &state)
{
static void g722_state_init(g722_state_t &state) {
state.itu_test_mode = false;
// 8 => 64 kbps; 7 => 56 kbps; 6 => 48 kbps
@ -102,8 +101,7 @@ class G722 : public sfl::AudioCodec {
return INT16_MIN;
}
void block4_encode(int band, int d)
{
void block4_encode(int band, int d) {
int wd1 = 0;
int wd2 = 0;
int wd3 = 0;
@ -207,8 +205,7 @@ class G722 : public sfl::AudioCodec {
}
void block4_decode(int band, int d)
{
void block4_decode(int band, int d) {
int wd1 = 0;
int wd2 = 0;
int wd3 = 0;

View File

@ -47,22 +47,23 @@ G729::G729() : sfl::AudioCodec(G729_PAYLOAD_TYPE, "G729", 8000, 160, 1),
encoder_(0),
decoder_(0)
{
handler_ = dlopen("libbcg729.so.0", RTLD_NOW);
if (!handler_)
throw std::runtime_error("g729: did not open shared lib");
handler_ = dlopen("libbcg729.so.0", RTLD_NOW);
encoder_ = G729_TYPE_ENCODER dlsym(handler_, "bcg729Encoder");
loadError(dlerror());
decoder_ = G729_TYPE_DECODER dlsym(handler_, "bcg729Decoder");
loadError(dlerror());
if (!handler_)
throw std::runtime_error("g729: did not open shared lib");
bcg729DecoderChannelContextStruct*(*decInit)() = G729_TYPE_DECODER_INIT dlsym(handler_, "initBcg729DecoderChannel");
loadError(dlerror());
bcg729EncoderChannelContextStruct*(*encInit)() = G729_TYPE_ENCODER_INIT dlsym(handler_, "initBcg729EncoderChannel");
loadError(dlerror());
encoder_ = G729_TYPE_ENCODER dlsym(handler_, "bcg729Encoder");
loadError(dlerror());
decoder_ = G729_TYPE_DECODER dlsym(handler_, "bcg729Decoder");
loadError(dlerror());
decoderContext_ = (*decInit)();
encoderContext_ = (*encInit)();
bcg729DecoderChannelContextStruct*(*decInit)() = G729_TYPE_DECODER_INIT dlsym(handler_, "initBcg729DecoderChannel");
loadError(dlerror());
bcg729EncoderChannelContextStruct*(*encInit)() = G729_TYPE_ENCODER_INIT dlsym(handler_, "initBcg729EncoderChannel");
loadError(dlerror());
decoderContext_ = (*decInit)();
encoderContext_ = (*encInit)();
}
G729::~G729()
@ -73,22 +74,22 @@ G729::~G729()
int G729::decode(short *dst, unsigned char *buf, size_t buffer_size)
{
decoder_(decoderContext_, buf, false, dst);
decoder_(decoderContext_, buf + (buffer_size / 2), false, dst + 80);
return 160;
decoder_(decoderContext_, buf, false, dst);
decoder_(decoderContext_, buf + (buffer_size / 2), false, dst + 80);
return 160;
}
int G729::encode(unsigned char *dst, short *src, size_t buffer_size)
{
encoder_(encoderContext_, src, dst);
encoder_(encoderContext_, src + (buffer_size / 2), dst + 10);
return 20;
encoder_(encoderContext_, src, dst);
encoder_(encoderContext_, src + (buffer_size / 2), dst + 10);
return 20;
}
void G729::loadError(const char *error)
{
if (error != NULL)
throw std::runtime_error("G729 failed to load");
if (error != NULL)
throw std::runtime_error("G729 failed to load");
}
// cppcheck-suppress unusedFunction

View File

@ -46,10 +46,10 @@ extern "C" {
class Gsm : public sfl::AudioCodec {
public:
public:
// _payload should be 3
Gsm() : sfl::AudioCodec(3, "GSM", 8000, 160, 1),
decode_gsmhandle_(NULL), encode_gsmhandle_(NULL) {
decode_gsmhandle_(NULL), encode_gsmhandle_(NULL) {
bitrate_ = 13.3;
hasDynamicPayload_ = false;
@ -60,8 +60,7 @@ public:
throw std::runtime_error("ERROR: encode_gsm_create\n");
}
~Gsm()
{
~Gsm() {
gsm_destroy(decode_gsmhandle_);
gsm_destroy(encode_gsmhandle_);
}

View File

@ -41,8 +41,7 @@ class Ilbc: public sfl::AudioCodec {
Ilbc() :
sfl::AudioCodec(ILBC_PAYLOAD, "iLBC", 8000, ILBC_FRAME_SIZE, 1),
ilbc_dec_(),
ilbc_enc_()
{
ilbc_enc_() {
bitrate_ = 13.3;
initDecode(&ilbc_dec_, 20, 1);

View File

@ -37,34 +37,37 @@ Opus::Opus() : sfl::AudioCodec(PAYLOAD_TYPE, "Opus", CLOCK_RATE, FRAME_SIZE, CHA
encoder_(0),
decoder_(0)
{
hasDynamicPayload_ = true;
hasDynamicPayload_ = true;
int err = 0;
encoder_ = opus_encoder_create(CLOCK_RATE, CHANNELS, OPUS_APPLICATION_VOIP, &err);
if (err)
throw std::runtime_error("opus: could not create encoder");
int err = 0;
encoder_ = opus_encoder_create(CLOCK_RATE, CHANNELS, OPUS_APPLICATION_VOIP, &err);
decoder_ = opus_decoder_create(CLOCK_RATE, CHANNELS, &err);
if (err)
throw std::runtime_error("opus: could not create decoder");
if (err)
throw std::runtime_error("opus: could not create encoder");
decoder_ = opus_decoder_create(CLOCK_RATE, CHANNELS, &err);
if (err)
throw std::runtime_error("opus: could not create decoder");
}
Opus::~Opus()
{
if (encoder_)
opus_encoder_destroy(encoder_);
if (decoder_)
opus_decoder_destroy(decoder_);
}
int Opus::decode(short *dst, unsigned char *buf, size_t buffer_size)
{
return opus_decode(decoder_, buf, buffer_size, dst, FRAME_SIZE, 0);
return opus_decode(decoder_, buf, buffer_size, dst, FRAME_SIZE, 0);
}
int Opus::encode(unsigned char *dst, short *src, size_t buffer_size)
{
return opus_encode(encoder_, src, FRAME_SIZE, dst, buffer_size * 2);
return opus_encode(encoder_, src, FRAME_SIZE, dst, buffer_size * 2);
}
int Opus::decode(std::vector<std::vector<short> > *dst, unsigned char *buf, size_t buffer_size, size_t dst_offset /* = 0 */)

View File

@ -44,6 +44,7 @@ void DcBlocker::doProcess(SFLAudioSample *out, SFLAudioSample *in, int samples,
for (unsigned i = 0; i < samples; ++i) {
state->x_ = in[i];
state->y_ = (SFLAudioSample) ((float) state->x_ - (float) state->xm1_ + 0.9999 * (float) state->y_);
state->xm1_ = state->x_;
state->ym1_ = state->y_;

View File

@ -38,26 +38,26 @@
namespace {
// decimation filter coefficient
const float decimationCoefs[] = {-0.09870257, 0.07473655, 0.05616626, 0.04448337, 0.03630817, 0.02944626,
0.02244098, 0.01463477, 0.00610982, -0.00266367, -0.01120109, -0.01873722,
-0.02373243, -0.02602213, -0.02437806, -0.01869834, -0.00875287, 0.00500204,
0.02183252, 0.04065763, 0.06015944, 0.0788299, 0.09518543, 0.10799179,
0.1160644, 0.12889288, 0.1160644, 0.10799179, 0.09518543, 0.0788299,
0.06015944, 0.04065763, 0.02183252, 0.00500204, -0.00875287, -0.01869834,
-0.02437806, -0.02602213, -0.02373243, -0.01873722, -0.01120109, -0.00266367,
0.00610982, 0.01463477, 0.02244098, 0.02944626, 0.03630817, 0.04448337,
0.05616626, 0.07473655, -0.09870257
};
0.02244098, 0.01463477, 0.00610982, -0.00266367, -0.01120109, -0.01873722,
-0.02373243, -0.02602213, -0.02437806, -0.01869834, -0.00875287, 0.00500204,
0.02183252, 0.04065763, 0.06015944, 0.0788299, 0.09518543, 0.10799179,
0.1160644, 0.12889288, 0.1160644, 0.10799179, 0.09518543, 0.0788299,
0.06015944, 0.04065763, 0.02183252, 0.00500204, -0.00875287, -0.01869834,
-0.02437806, -0.02602213, -0.02373243, -0.01873722, -0.01120109, -0.00266367,
0.00610982, 0.01463477, 0.02244098, 0.02944626, 0.03630817, 0.04448337,
0.05616626, 0.07473655, -0.09870257
};
std::vector<double> ird(decimationCoefs, decimationCoefs + sizeof(decimationCoefs) /sizeof(float));
// decimation filter coefficient
const float bandpassCoefs[] = {0.06278034, -0.0758545, -0.02274943, -0.0084497, 0.0702427, 0.05986113,
0.06436469, -0.02412049, -0.03433526, -0.07568665, -0.03214543, -0.07236507,
-0.06979052, -0.12446371, -0.05530828, 0.00947243, 0.15294699, 0.17735563,
0.15294699, 0.00947243, -0.05530828, -0.12446371, -0.06979052, -0.07236507,
-0.03214543, -0.07568665, -0.03433526, -0.02412049, 0.06436469, 0.05986113,
0.0702427, -0.0084497, -0.02274943, -0.0758545, 0.06278034
};
0.06436469, -0.02412049, -0.03433526, -0.07568665, -0.03214543, -0.07236507,
-0.06979052, -0.12446371, -0.05530828, 0.00947243, 0.15294699, 0.17735563,
0.15294699, 0.00947243, -0.05530828, -0.12446371, -0.06979052, -0.07236507,
-0.03214543, -0.07568665, -0.03433526, -0.02412049, 0.06436469, 0.05986113,
0.0702427, -0.0084497, -0.02274943, -0.0758545, 0.06278034
};
std::vector<double> irb(bandpassCoefs, bandpassCoefs + sizeof(bandpassCoefs) / sizeof(float));
} // end anonymous namespace

View File

@ -111,6 +111,7 @@ double GainControl::DetectionAverage::getAverage(double in)
previous_y_ = ((1.0 - g_a_) * in) + (g_a_ * previous_y_);
else
previous_y_ = ((1.0 - g_r_) * in) + (g_r_ * previous_y_);
return previous_y_;
}
@ -120,7 +121,7 @@ GainControl::Limiter::Limiter(double r, double thresh) : ratio_(r), threshold_(t
double GainControl::Limiter::limit(double in) const
{
double out = (in > threshold_ ? (ratio_ * (in - threshold_)) + threshold_ :
in < -threshold_ ? (ratio_ * (in + threshold_)) - threshold_ : in);
in < -threshold_ ? (ratio_ * (in + threshold_)) - threshold_ : in);
return out;
}

View File

@ -49,6 +49,7 @@ MainBuffer::~MainBuffer()
// delete any ring buffers that didn't get removed
for (RingBufferMap::iterator iter = ringBufferMap_.begin(); iter != ringBufferMap_.end(); ++iter)
delete iter->second;
pthread_mutex_destroy(&mutex_);
}
@ -88,6 +89,7 @@ void MainBuffer::removeCallIDSet(const std::string &set_id)
void MainBuffer::addCallIDtoSet(const std::string &set_id, const std::string &call_id)
{
CallIDSet* callid_set = getCallIDSet(set_id);
if (callid_set)
callid_set->insert(call_id);
else
@ -229,7 +231,7 @@ void MainBuffer::unBindAll(const std::string & call_id)
CallIDSet temp_set(*callid_set);
for (CallIDSet::iterator iter_set = temp_set.begin();
iter_set != temp_set.end(); ++iter_set) {
iter_set != temp_set.end(); ++iter_set) {
std::string call_id_in_set(*iter_set);
unBindCallID(call_id, call_id_in_set);
}
@ -323,6 +325,7 @@ size_t MainBuffer::availableForGet(const std::string &call_id)
} else {
size_t availableSamples = INT_MAX;
for (CallIDSet::iterator i = callid_set->begin(); i != callid_set->end(); ++i) {
const size_t nbSamples = availableForGetByID(*i, call_id);
@ -335,7 +338,7 @@ size_t MainBuffer::availableForGet(const std::string &call_id)
}
size_t MainBuffer::availableForGetByID(const std::string &call_id,
const std::string &reader_id) const
const std::string &reader_id) const
{
if (call_id != DEFAULT_ID and reader_id == call_id)
ERROR("RingBuffer has a readpointer on itself");
@ -405,6 +408,7 @@ void MainBuffer::flushAllBuffers()
void MainBuffer::dumpInfo()
{
sfl::ScopedLock guard(mutex_);
// print each call and bound call ids
for (CallIDMap::const_iterator iter_call = callIDMap_.begin(); iter_call != callIDMap_.end(); ++iter_call) {
std::string dbg_str(" Call: \t");
@ -429,6 +433,7 @@ void MainBuffer::dumpInfo()
dbg_str.append(" as read pointer: \t");
RingBuffer* rbuffer = iter_buffer->second;
if (rbuffer) {
ReadPointer* rpointer = rbuffer->getReadPointerList();
@ -439,6 +444,7 @@ void MainBuffer::dumpInfo()
}
}
}
DEBUG("%s", dbg_str.c_str());
}
}

View File

@ -69,7 +69,7 @@ void stream_moved_callback(pa_stream *s, void *userdata UNUSED)
} // end anonymous namespace
#ifdef RECTODISK
std::ofstream outfileResampled ("testMicOuputResampled.raw", std::ifstream::binary);
std::ofstream outfileResampled("testMicOuputResampled.raw", std::ifstream::binary);
std::ofstream outfile("testMicOuput.raw", std::ifstream::binary);
#endif
@ -94,8 +94,10 @@ PulseLayer::PulseLayer(AudioPreference &pref)
pa_proplist_sets(pl, PA_PROP_MEDIA_ROLE, "phone");
context_ = pa_context_new_with_proplist(pa_threaded_mainloop_get_api(mainloop_), "SFLphone", pl);
if (pl)
pa_proplist_free(pl);
#else
setenv("PULSE_PROP_media.role", "phone", 1);
context_ = pa_context_new(pa_threaded_mainloop_get_api(mainloop_), "SFLphone");
@ -150,7 +152,7 @@ void PulseLayer::context_state_callback(pa_context* c, void *user_data)
PulseLayer *pulse = static_cast<PulseLayer*>(user_data);
assert(c and pulse and pulse->mainloop_);
const pa_subscription_mask_t mask = (pa_subscription_mask_t)
(PA_SUBSCRIPTION_MASK_SINK | PA_SUBSCRIPTION_MASK_SOURCE);
(PA_SUBSCRIPTION_MASK_SINK | PA_SUBSCRIPTION_MASK_SOURCE);
switch (pa_context_get_state(c)) {
case PA_CONTEXT_CONNECTING:
@ -186,6 +188,7 @@ void PulseLayer::updateSinkList()
sinkList_.clear();
enumeratingSinks_ = true;
pa_operation *op = pa_context_get_sink_info_list(context_, sink_input_info_callback, this);
if (op != NULL)
pa_operation_unref(op);
}
@ -195,6 +198,7 @@ void PulseLayer::updateSourceList()
sourceList_.clear();
enumeratingSources_ = true;
pa_operation *op = pa_context_get_source_info_list(context_, source_input_info_callback, this);
if (op != NULL)
pa_operation_unref(op);
}
@ -236,9 +240,11 @@ std::vector<std::string> PulseLayer::getPlaybackDeviceList() const
int PulseLayer::getAudioDeviceIndex(const std::string& name) const
{
int index = std::distance(sourceList_.begin(), std::find_if(sourceList_.begin(), sourceList_.end(), PaDeviceInfos::nameComparator(name)));
if (index == std::distance(sourceList_.begin(), sourceList_.end())) {
index = std::distance(sinkList_.begin(), std::find_if(sinkList_.begin(), sinkList_.end(), PaDeviceInfos::nameComparator(name)));
}
return index;
}
@ -260,12 +266,14 @@ std::string PulseLayer::getAudioDeviceName(int index, PCMType type) const
return "";
}
return sinkList_[index].name;
case SFL_PCM_CAPTURE:
if (index < 0 or static_cast<size_t>(index) >= sourceList_.size()) {
ERROR("Index %d out of range", index);
return "";
}
return sourceList_[index].name;
default:
return "";
}
@ -324,13 +332,13 @@ void PulseLayer::createStreams(pa_context* c)
}
namespace {
// Delete stream and zero out its pointer
void
cleanupStream(AudioStream *&stream)
{
delete stream;
stream = 0;
}
// Delete stream and zero out its pointer
void
cleanupStream(AudioStream *&stream)
{
delete stream;
stream = 0;
}
}
@ -403,6 +411,7 @@ void PulseLayer::writeToSpeaker()
}
SFLAudioSample *data = 0;
if (urgentBytes) {
AudioBuffer linearbuff(urgentSamples, n_channels);
pa_stream_begin_write(s, (void**)&data, &urgentBytes);
@ -449,6 +458,7 @@ void PulseLayer::writeToSpeaker()
unsigned int mainBufferSampleRate = Manager::instance().getMainBuffer().getInternalSamplingRate();
bool resample = sampleRate_ != mainBufferSampleRate;
if (resample) {
resampleFactor = (double) sampleRate_ / mainBufferSampleRate;
readableSamples = (double) readableSamples / resampleFactor;
@ -564,9 +574,9 @@ void PulseLayer::ringtoneToSpeaker()
//applyGain(static_cast<SFLAudioSample *>(data), bytes / sizeof(SFLAudioSample), getPlaybackGain());
fileToPlay->getNext(tmp, getPlaybackGain());
tmp.interleave((SFLAudioSample*)data);
}
else
} else {
memset(data, 0, bytes);
}
pa_stream_write(s, data, bytes, NULL, 0, PA_SEEK_RELATIVE);
}
@ -577,8 +587,9 @@ PulseLayer::context_changed_callback(pa_context* c,
uint32_t idx UNUSED, void *userdata)
{
PulseLayer *context = static_cast<PulseLayer*>(userdata);
switch (type & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) {
pa_operation *op;
pa_operation *op;
case PA_SUBSCRIPTION_EVENT_SINK:
switch (type & PA_SUBSCRIPTION_EVENT_TYPE_MASK) {
@ -587,11 +598,14 @@ PulseLayer::context_changed_callback(pa_context* c,
DEBUG("Updating sink list");
context->sinkList_.clear();
op = pa_context_get_sink_info_list(c, sink_input_info_callback, userdata);
if (op != NULL)
pa_operation_unref(op);
default:
break;
}
break;
case PA_SUBSCRIPTION_EVENT_SOURCE:
@ -601,12 +615,16 @@ PulseLayer::context_changed_callback(pa_context* c,
DEBUG("Updating source list");
context->sourceList_.clear();
op = pa_context_get_source_info_list(c, source_input_info_callback, userdata);
if (op != NULL)
pa_operation_unref(op);
default:
break;
}
break;
default:
DEBUG("Unhandled event type 0x%x", type);
break;
@ -625,29 +643,29 @@ void PulseLayer::source_input_info_callback(pa_context *c UNUSED, const pa_sourc
}
DEBUG("Source %u\n"
" Name: %s\n"
" Driver: %s\n"
" Description: %s\n"
" Sample Specification: %s\n"
" Channel Map: %s\n"
" Owner Module: %u\n"
" Volume: %s\n"
" Monitor if Sink: %u\n"
" Latency: %0.0f usec\n"
" Flags: %s%s%s\n",
i->index,
i->name,
i->driver,
i->description,
pa_sample_spec_snprint(s, sizeof(s), &i->sample_spec),
pa_channel_map_snprint(cm, sizeof(cm), &i->channel_map),
i->owner_module,
i->mute ? "muted" : pa_cvolume_snprint(cv, sizeof(cv), &i->volume),
i->monitor_of_sink,
(double) i->latency,
i->flags & PA_SOURCE_HW_VOLUME_CTRL ? "HW_VOLUME_CTRL " : "",
i->flags & PA_SOURCE_LATENCY ? "LATENCY " : "",
i->flags & PA_SOURCE_HARDWARE ? "HARDWARE" : "");
" Name: %s\n"
" Driver: %s\n"
" Description: %s\n"
" Sample Specification: %s\n"
" Channel Map: %s\n"
" Owner Module: %u\n"
" Volume: %s\n"
" Monitor if Sink: %u\n"
" Latency: %0.0f usec\n"
" Flags: %s%s%s\n",
i->index,
i->name,
i->driver,
i->description,
pa_sample_spec_snprint(s, sizeof(s), &i->sample_spec),
pa_channel_map_snprint(cm, sizeof(cm), &i->channel_map),
i->owner_module,
i->mute ? "muted" : pa_cvolume_snprint(cv, sizeof(cv), &i->volume),
i->monitor_of_sink,
(double) i->latency,
i->flags & PA_SOURCE_HW_VOLUME_CTRL ? "HW_VOLUME_CTRL " : "",
i->flags & PA_SOURCE_LATENCY ? "LATENCY " : "",
i->flags & PA_SOURCE_HARDWARE ? "HARDWARE" : "");
if (not context->inSourceList(i->name)) {
PaDeviceInfos ep_infos(i->index, i->name, i->sample_spec, i->channel_map);
@ -699,19 +717,23 @@ void PulseLayer::sink_input_info_callback(pa_context *c UNUSED, const pa_sink_in
void PulseLayer::updatePreference(AudioPreference &preference, int index, PCMType type)
{
const std::string devName(getAudioDeviceName(index, type));
switch (type) {
case SFL_PCM_PLAYBACK:
DEBUG("setting %s for playback", devName.c_str());
preference.setPulseDevicePlayback(devName);
break;
case SFL_PCM_CAPTURE:
DEBUG("setting %s for capture", devName.c_str());
preference.setPulseDeviceRecord(devName);
break;
case SFL_PCM_RINGTONE:
DEBUG("setting %s for ringer", devName.c_str());
preference.setPulseDeviceRingtone(devName);
break;
default:
break;
}

View File

@ -41,8 +41,8 @@
#include "ringbuffer.h"
namespace {
// corresponds to 160 ms (about 5 rtp packets)
const size_t MIN_BUFFER_SIZE = 1280;
// corresponds to 160 ms (about 5 rtp packets)
const size_t MIN_BUFFER_SIZE = 1280;
}
// Create a ring buffer with 'size' bytes
@ -192,6 +192,7 @@ void RingBuffer::put(AudioBuffer& buf)
pos = (pos + block) % buffer_size;
toCopy -= block;
}
endPos_ = pos;
}

View File

@ -71,8 +71,7 @@ bool DTMF::generateDTMF(vector<SFLAudioSample> &buffer)
dtmfgenerator_.getSamples(buffer, newTone_);
currentTone_ = newTone_;
return true;
}
else
} else
return false;
}
} catch (const DTMFException &e) {

View File

@ -111,6 +111,7 @@ void DTMFGenerator::getSamples(vector<SFLAudioSample> &buffer, unsigned char cod
size_t i;
const size_t n = buffer.size();
for (i = 0; i < n; ++i)
buffer[i] = state.sample[i % sampleRate_];
@ -128,6 +129,7 @@ void DTMFGenerator::getNextSamples(vector<SFLAudioSample> &buffer)
size_t i;
const size_t n = buffer.size();
for (i = 0; i < n; i++)
buffer[i] = state.sample[(state.offset + i) % sampleRate_];