Commit 7f1d6c40 authored by Tristan Matthews's avatar Tristan Matthews
Browse files

Merge branch 'master' of http://git.sflphone.org/sflphone into video_preview

Resolved Conflicts:
	daemon/src/sip/sdp.cpp
	gnome/src/main.c
parents 7dc83853 fe7453e0
......@@ -165,7 +165,8 @@ DBUS_CPP_REQUIRED_VERSION=0.6.0-pre1
PKG_CHECK_MODULES(DBUSCPP, dbus-c++-1,,
AC_MSG_ERROR([You need the DBus-c++ libraries (version $DBUS_CPP_REQUIRED_VERSION or better)]))
AX_LIB_EXPAT
AX_LIB_EXPAT([2.0.1])
AS_IF([test "$HAVE_EXPAT" != "yes"], [AC_MSG_ERROR([libexpat could not be found, which is required to build this package.])], [])
AX_PTHREAD
......
......@@ -35,10 +35,6 @@
#include <string>
#include <vector>
#if HAVE_CONFIG_H
#include "config.h"
#endif
#include "global.h"
#include "noncopyable.h"
#include "config/sfl_config.h"
......
......@@ -41,7 +41,7 @@
#include <cassert>
#include "logger.h"
AudioLoop::AudioLoop() : buffer_(0), size_(0), pos_(0), sampleRate_(0), isRecording_(false)
AudioLoop::AudioLoop(unsigned int sampleRate) : buffer_(0), size_(0), pos_(0), sampleRate_(sampleRate), isRecording_(false)
{}
AudioLoop::~AudioLoop()
......@@ -52,9 +52,6 @@ AudioLoop::~AudioLoop()
void
AudioLoop::seek(double relative_position)
{
DEBUG("seek relative position: %f", relative_position);
size_t new_pos = (size_t)((double)size_ * (relative_position * 0.01));
pos_ = new_pos;
......@@ -100,10 +97,17 @@ AudioLoop::getNext(SFLDataFormat* output, size_t total_samples, short volume)
pos_ = pos;
// We want to send values in milisecond
int divisor = sampleRate_ / 1000;
if(divisor == 0) {
ERROR("Error cannot update playback slider, sampling rate is 0");
return;
}
if(isRecording_) {
if((updatePlaybackScale % 5) == 0) {
CallManager *cm = Manager::instance().getDbusManager()->getCallManager();
cm->updatePlaybackScale("", (pos_ >> 8) + ((size_ >> 8) << 16));
cm->updatePlaybackScale(pos_ / divisor, size_ / divisor);
}
updatePlaybackScale++;
}
......
......@@ -44,7 +44,7 @@
class AudioLoop {
public:
AudioLoop();
AudioLoop(unsigned int sampleRate);
virtual ~AudioLoop();
......
......@@ -48,18 +48,9 @@ class SIPCall;
namespace sfl {
// Frequency (in packet number)
#define RTP_TIMESTAMP_RESET_FREQ 100
static const int schedulingTimeout = 4000;
static const int expireTimeout = 1000000;
// G.722 VoIP is typically carried in RTP payload type 9.[2] Note that IANA records the clock rate for type 9 G.722 as 8 kHz
// (instead of 16 kHz), RFC3551[3] clarifies that this is due to a historical error and is retained in order to maintain backward
// compatibility. Consequently correct implementations represent the value 8,000 where required but encode and decode audio at 16 kHz.
static const int g722PayloadType = 9;
static const int g722RtpClockRate = 8000;
static const int g722RtpTimeincrement = 160;
inline uint32
timeval2microtimeout(const timeval& t)
......
......@@ -79,34 +79,22 @@ void AudioRtpSession::setSessionMedia(AudioCodec &audioCodec)
{
setRtpMedia(&audioCodec);
// store codec info locally
int payloadType = getCodecPayloadType();
int frameSize = getCodecFrameSize();
int smplRate = getCodecSampleRate();
bool dynamic = getHasDynamicPayload();
// G722 requires timestamp to be incremented at 8kHz
if (payloadType == g722PayloadType)
timestampIncrement_ = g722RtpTimeincrement;
else
timestampIncrement_ = frameSize;
DEBUG("Codec payload: %d", payloadType);
DEBUG("Codec sampling rate: %d", smplRate);
DEBUG("Codec frame size: %d", frameSize);
DEBUG("RTP timestamp increment: %d", timestampIncrement_);
if (payloadType == g722PayloadType) {
DEBUG("Setting G722 payload format");
queue_.setPayloadFormat(ost::DynamicPayloadFormat((ost::PayloadType) payloadType, g722RtpClockRate));
const ost::PayloadType payloadType = getCodecPayloadType();
if (payloadType == ost::sptG722) {
const int G722_RTP_TIME_INCREMENT = 160;
timestampIncrement_ = G722_RTP_TIME_INCREMENT;
} else
timestampIncrement_ = getCodecFrameSize();
if (payloadType == ost::sptG722) {
const int G722_RTP_CLOCK_RATE = 8000;
queue_.setPayloadFormat(ost::DynamicPayloadFormat( payloadType, G722_RTP_CLOCK_RATE));
} else {
if (dynamic) {
DEBUG("Setting dynamic payload format");
queue_.setPayloadFormat(ost::DynamicPayloadFormat((ost::PayloadType) payloadType, smplRate));
} else {
DEBUG("Setting static payload format");
queue_.setPayloadFormat(ost::StaticPayloadFormat((ost::StaticPayloadType) payloadType));
}
if (getHasDynamicPayload())
queue_.setPayloadFormat(ost::DynamicPayloadFormat(payloadType, getCodecSampleRate()));
else
queue_.setPayloadFormat(ost::StaticPayloadFormat(static_cast<ost::StaticPayloadType>(payloadType)));
}
}
......@@ -186,11 +174,13 @@ void AudioRtpSession::sendMicData()
void AudioRtpSession::setSessionTimeouts()
{
const int schedulingTimeout = 4000;
const int expireTimeout = 1000000;
DEBUG("Set session scheduling timeout (%d) and expireTimeout (%d)",
sfl::schedulingTimeout, sfl::expireTimeout);
schedulingTimeout, expireTimeout);
queue_.setSchedulingTimeout(sfl::schedulingTimeout);
queue_.setExpireTimeout(sfl::expireTimeout);
queue_.setSchedulingTimeout(schedulingTimeout);
queue_.setExpireTimeout(expireTimeout);
}
void AudioRtpSession::setDestinationIpAddress()
......
......@@ -32,6 +32,7 @@
#include "mainbuffer.h"
#include "ringbuffer.h"
#include "sfl_types.h" // for SIZEBUF
#include <climits>
#include <utility> // for std::pair
#include "logger.h"
......@@ -55,50 +56,45 @@ void MainBuffer::setInternalSamplingRate(int sr)
}
}
CallIDSet* MainBuffer::getCallIDSet(const std::string & call_id)
CallIDSet* MainBuffer::getCallIDSet(const std::string &call_id)
{
CallIDMap::iterator iter = callIDMap_.find(call_id);
return (iter != callIDMap_.end()) ? iter->second : NULL;
}
void MainBuffer::createCallIDSet(const std::string & set_id)
void MainBuffer::createCallIDSet(const std::string &set_id)
{
callIDMap_.insert(std::pair<std::string, CallIDSet*> (set_id, new CallIDSet));
if (getCallIDSet(set_id) == NULL)
callIDMap_[set_id] = new CallIDSet;
else
ERROR("CallID set %s already exists, ignoring", set_id.c_str());
}
bool MainBuffer::removeCallIDSet(const std::string & set_id)
void MainBuffer::removeCallIDSet(const std::string &set_id)
{
CallIDSet* callid_set = getCallIDSet(set_id);
if (!callid_set) {
DEBUG("CallID set %s does not exist!", set_id.c_str());
return false;
}
if (callIDMap_.erase(set_id) == 0) {
DEBUG("CallID set %s not found!", set_id.c_str());
return false;
}
delete callid_set;
callid_set = NULL;
return true;
if (callid_set) {
callIDMap_.erase(set_id);
delete callid_set;
} else
ERROR("CallID set %s does not exist!", set_id.c_str());
}
void MainBuffer::addCallIDtoSet(const std::string & set_id, const std::string & call_id)
void MainBuffer::addCallIDtoSet(const std::string &set_id, const std::string &call_id)
{
CallIDSet* callid_set = getCallIDSet(set_id);
callid_set->insert(call_id);
}
void MainBuffer::removeCallIDfromSet(const std::string & set_id, const std::string & call_id)
void MainBuffer::removeCallIDfromSet(const std::string &set_id, const std::string &call_id)
{
CallIDSet* callid_set = getCallIDSet(set_id);
if (callid_set == NULL)
if (callid_set)
callid_set->erase(call_id);
else
ERROR("CallIDSet %s does not exist!", set_id.c_str());
else if (callid_set->erase(call_id) == 0)
ERROR("Could not find callID %s in set %s!", call_id.c_str(), set_id.c_str());
}
RingBuffer* MainBuffer::getRingBuffer(const std::string & call_id)
......@@ -107,46 +103,33 @@ RingBuffer* MainBuffer::getRingBuffer(const std::string & call_id)
return (iter != ringBufferMap_.end()) ? iter->second : NULL;
}
RingBuffer* MainBuffer::createRingBuffer(const std::string & call_id)
void MainBuffer::createRingBuffer(const std::string &call_id)
{
RingBuffer* newRingBuffer = new RingBuffer(SIZEBUF, call_id);
ringBufferMap_.insert(std::pair<std::string, RingBuffer*> (call_id, newRingBuffer));
return newRingBuffer;
if (!getRingBuffer(call_id))
ringBufferMap_[call_id] = new RingBuffer(SIZEBUF, call_id);
else
ERROR("Ringbuffer already exists for call_id %s", call_id.c_str());
}
bool MainBuffer::removeRingBuffer(const std::string & call_id)
void MainBuffer::removeRingBuffer(const std::string &call_id)
{
RingBuffer* ring_buffer = getRingBuffer(call_id);
if (ring_buffer != NULL) {
if (ringBufferMap_.erase(call_id) != 0) {
delete ring_buffer;
return true;
} else {
ERROR("Fail to delete ringbuffer %s!", call_id.c_str());
return false;
}
} else {
if (ring_buffer) {
ringBufferMap_.erase(call_id);
delete ring_buffer;
} else
DEBUG("Ringbuffer %s does not exist!", call_id.c_str());
return true;
}
}
void MainBuffer::bindCallID(const std::string & call_id1, const std::string & call_id2)
{
ost::MutexLock guard(mutex_);
if (getRingBuffer(call_id1) == NULL)
createRingBuffer(call_id1);
if (getCallIDSet(call_id1) == NULL)
createCallIDSet(call_id1);
if (getRingBuffer(call_id2) == NULL)
createRingBuffer(call_id2);
if (getCallIDSet(call_id2) == NULL)
createCallIDSet(call_id2);
createRingBuffer(call_id1);
createCallIDSet(call_id1);
createRingBuffer(call_id2);
createCallIDSet(call_id2);
getRingBuffer(call_id1)->createReadPointer(call_id2);
getRingBuffer(call_id2)->createReadPointer(call_id1);
......@@ -162,9 +145,7 @@ void MainBuffer::bindHalfDuplexOut(const std::string & process_id, const std::st
if (!getRingBuffer(call_id))
return;
if (!getCallIDSet(process_id))
createCallIDSet(process_id);
createCallIDSet(process_id);
getRingBuffer(call_id)->createReadPointer(process_id);
addCallIDtoSet(process_id, call_id);
}
......@@ -257,7 +238,7 @@ int MainBuffer::getData(void *buffer, int toCopy, const std::string &call_id)
CallIDSet* callid_set = getCallIDSet(call_id);
if (not callid_set or callid_set->empty())
if (callid_set == NULL or callid_set->empty())
return 0;
if (callid_set->size() == 1) {
......@@ -281,8 +262,9 @@ int MainBuffer::getData(void *buffer, int toCopy, const std::string &call_id)
size = getDataByID(mixBuffer, toCopy, *iter_id, call_id);
if (size > 0) {
SFLDataFormat *dest = static_cast<SFLDataFormat*>(buffer);
for (int k = 0; k < nbSmplToCopy; ++k)
((SFLDataFormat*)(buffer))[k] += mixBuffer[k];
dest[k] += mixBuffer[k];
}
}
......@@ -302,43 +284,35 @@ int MainBuffer::availForGet(const std::string & call_id)
CallIDSet* callid_set = getCallIDSet(call_id);
if (callid_set == NULL)
return 0;
if (callid_set->empty())
if (callid_set == NULL or callid_set->empty())
return 0;
if (callid_set->size() == 1) {
CallIDSet::iterator iter_id = callid_set->begin();
if ((call_id != DEFAULT_ID) && (*iter_id == call_id))
DEBUG("This problem should not occur since we have %i element", (int) callid_set->size());
DEBUG("This problem should not occur since we have %ld elements", callid_set->size());
return availForGetByID(*iter_id, call_id);
} else {
int avail_bytes = 99999;
int nb_bytes;
CallIDSet::iterator iter_id = callid_set->begin();
int avail_bytes = INT_MAX;
for (CallIDSet::iterator i = callid_set->begin(); i != callid_set->end(); ++i) {
const int nb_bytes = availForGetByID(*i, call_id);
syncBuffers(call_id);
for (iter_id = callid_set->begin(); iter_id != callid_set->end(); ++iter_id) {
nb_bytes = availForGetByID(*iter_id, call_id);
if ((nb_bytes != 0) && (nb_bytes < avail_bytes))
avail_bytes = nb_bytes;
if (nb_bytes != 0)
avail_bytes = std::min(avail_bytes, nb_bytes);
}
return avail_bytes != 99999 ? avail_bytes : 0;
return avail_bytes != INT_MAX ? avail_bytes : 0;
}
}
int MainBuffer::availForGetByID(const std::string &call_id,
const std::string &reader_id)
{
if ((call_id != DEFAULT_ID) and (reader_id == call_id))
if (call_id != DEFAULT_ID and reader_id == call_id)
ERROR("RingBuffer has a readpointer on itself");
RingBuffer* ringbuffer = getRingBuffer(call_id);
......@@ -392,7 +366,7 @@ void MainBuffer::flushByID(const std::string & call_id, const std::string & read
{
RingBuffer* ringbuffer = getRingBuffer(call_id);
if (ringbuffer != NULL)
if (ringbuffer)
ringbuffer->flush(reader_id);
}
......@@ -403,33 +377,6 @@ void MainBuffer::flushAllBuffers()
iter->second->flushAll();
}
void MainBuffer::syncBuffers(const std::string & call_id)
{
CallIDSet* callid_set = getCallIDSet(call_id);
if (callid_set || callid_set->empty())
return;
if (callid_set->size() == 1) // no need to resync, only one session
return;
float mean_nbBytes = 0.0;
// compute mean nb byte in buffers
for (CallIDSet::iterator iter = callid_set->begin();
iter != callid_set->end(); ++iter)
mean_nbBytes += availForGetByID(*iter, call_id);
mean_nbBytes /= static_cast<float>(callid_set->size());
// resync buffers in this conference according to the computed mean
for (CallIDSet::iterator iter = callid_set->begin();
iter != callid_set->end(); ++iter)
if (availForGetByID(*iter, call_id) > (mean_nbBytes + 640))
discardByID(640, *iter, call_id);
}
void MainBuffer::stateInfo()
{
// print each call and bound call ids
......@@ -450,21 +397,20 @@ void MainBuffer::stateInfo()
// Print ringbuffers ids and readpointers
for (RingBufferMap::iterator iter_buffer = ringBufferMap_.begin(); iter_buffer != ringBufferMap_.end(); ++iter_buffer) {
RingBuffer* rbuffer = iter_buffer->second;
ReadPointer* rpointer = NULL;
std::string dbg_str(" Buffer: \t");
dbg_str.append(iter_buffer->first);
dbg_str.append(" as read pointer: \t");
if (rbuffer)
rpointer = rbuffer->getReadPointerList();
if (rpointer) {
for (ReadPointer::iterator iter = rpointer->begin(); iter != rpointer->end(); ++iter) {
dbg_str.append(iter->first);
dbg_str.append(", ");
RingBuffer* rbuffer = iter_buffer->second;
if (rbuffer) {
ReadPointer* rpointer = rbuffer->getReadPointerList();
if (rpointer) {
for (ReadPointer::iterator iter = rpointer->begin(); iter != rpointer->end(); ++iter) {
dbg_str.append(iter->first);
dbg_str.append(", ");
}
}
}
DEBUG("%s", dbg_str.c_str());
......
......@@ -40,12 +40,8 @@
class RingBuffer;
typedef std::map<std::string, RingBuffer*> RingBufferMap;
typedef std::set<std::string> CallIDSet;
typedef std::map<std::string, CallIDSet*> CallIDMap;
class MainBuffer {
public:
......@@ -98,8 +94,6 @@ class MainBuffer {
void flushAllBuffers();
void syncBuffers(const std::string &call_id);
void stateInfo();
private:
......@@ -108,7 +102,7 @@ class MainBuffer {
void createCallIDSet(const std::string &set_id);
bool removeCallIDSet(const std::string &set_id);
void removeCallIDSet(const std::string &set_id);
/**
* Add a new call id to this set
......@@ -120,9 +114,9 @@ class MainBuffer {
/**
* Create a new ringbuffer with default readpointer
*/
RingBuffer* createRingBuffer(const std::string &call_id);
void createRingBuffer(const std::string &call_id);
bool removeRingBuffer(const std::string &call_id);
void removeRingBuffer(const std::string &call_id);
RingBuffer* getRingBuffer(const std::string &call_id);
......@@ -134,8 +128,10 @@ class MainBuffer {
void flushByID(const std::string &call_id, const std::string &reader_id);
typedef std::map<std::string, RingBuffer*> RingBufferMap;
RingBufferMap ringBufferMap_;
typedef std::map<std::string, CallIDSet*> CallIDMap;
CallIDMap callIDMap_;
ost::Mutex mutex_;
......
......@@ -33,7 +33,7 @@
#include "logger.h"
#include <stdexcept>
AudioStream::AudioStream(pa_context *c, pa_threaded_mainloop *m, const char *desc, int type, int smplrate, std::string& deviceName)
AudioStream::AudioStream(pa_context *c, pa_threaded_mainloop *m, const char *desc, int type, unsigned samplrate, std::string& deviceName)
: audiostream_(0), mainloop_(m)
{
static const pa_channel_map channel_map = {
......@@ -43,7 +43,7 @@ AudioStream::AudioStream(pa_context *c, pa_threaded_mainloop *m, const char *des
pa_sample_spec sample_spec = {
PA_SAMPLE_S16LE, // PA_SAMPLE_FLOAT32LE,
smplrate,
samplrate,
1
};
......
......@@ -55,7 +55,7 @@ class AudioStream {
* @param audio sampling rate
* @param device name
*/
AudioStream(pa_context *, pa_threaded_mainloop *, const char *, int, int, std::string&);
AudioStream(pa_context *, pa_threaded_mainloop *, const char *, int, unsigned, std::string&);
~AudioStream();
......
......@@ -43,7 +43,7 @@
#include "logger.h"
RawFile::RawFile(const std::string& name, sfl::AudioCodec *codec, unsigned int sampleRate)
: AudioFile(name), audioCodec_(codec)
: AudioFile(name, sampleRate), audioCodec_(codec)
{
if (filepath_.empty())
throw AudioFileException("Unable to open audio file: filename is empty");
......@@ -109,7 +109,7 @@ RawFile::RawFile(const std::string& name, sfl::AudioCodec *codec, unsigned int s
}
WaveFile::WaveFile(const std::string &fileName, int newRate) : AudioFile(fileName)
WaveFile::WaveFile(const std::string &fileName, unsigned int sampleRate) : AudioFile(fileName, sampleRate)
{
const std::fstream fs(fileName.c_str(), std::ios_base::in);
......@@ -174,7 +174,8 @@ WaveFile::WaveFile(const std::string &fileName, int newRate) : AudioFile(fileNam
fileStream.read(data, sizeof data / sizeof *data);
// Samplerate converter initialized with 88200 sample long
SamplerateConverter converter(std::max(fileRate, newRate));
const int rate = static_cast<SINT32>(sampleRate_);
SamplerateConverter converter(std::max(fileRate, rate));
// Get length of data from the header.
SINT32 bytes;
......@@ -200,15 +201,13 @@ WaveFile::WaveFile(const std::string &fileName, int newRate) : AudioFile(fileNam
nbSamples *= 0.5;
}
if (fileRate != newRate) {
const float ratio = newRate / (float) fileRate;
if (fileRate != rate) {
const float ratio = sampleRate_ / (float) fileRate;
const int outSamples = ceil(nbSamples * ratio);
size_ = outSamples;
buffer_ = new SFLDataFormat[size_];
converter.resample(tempBuffer, buffer_, size_, fileRate, newRate, nbSamples);
converter.resample(tempBuffer, buffer_, size_, fileRate, sampleRate_, nbSamples);
delete [] tempBuffer;
} else
buffer_ = tempBuffer;
sampleRate_ = newRate;
}
......@@ -52,7 +52,9 @@ class AudioFileException : public std::runtime_error {
*/
class AudioFile : public AudioLoop {
public:
AudioFile(const std::string &filepath) : filepath_(filepath) {}
AudioFile(const std::string &filepath, unsigned int sampleRate) : AudioLoop(sampleRate), filepath_(filepath)
{}
std::string getFilePath() const {
return filepath_;
}
......@@ -80,10 +82,10 @@ class WaveFile : public AudioFile {
public:
/**
* Load a sound file in memory
* @param filename The absolute path to the file
* @param sampleRate The sample rate to read it
* @param filename The absolute path to the file
* @param sampleRate The sample rate to read it
*/
WaveFile(const std::string&, int);
WaveFile(const std::string&, unsigned int sampleRate);
};
#endif // __AUDIOFILE_H__
......@@ -44,7 +44,7 @@
#include <vector>