2
* Copyright (C) 2004, 2005, 2006, 2008, 2009, 2010, 2011 Savoir-Faire Linux Inc.
2
* Copyright (C) 2004-2012 Savoir-Faire Linux Inc.
3
3
* Author : Alexandre Savard <alexandre.savard@savoirfairelinux.com>
6
5
* This program is free software; you can redistribute it and/or modify
7
6
* it under the terms of the GNU General Public License as published by
8
7
* the Free Software Foundation; either version 3 of the License, or
16
15
* You should have received a copy of the GNU General Public License
17
16
* along with this program; if not, write to the Free Software
18
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20
19
* Additional permission under GNU GPL version 3 section 7:
32
31
#include "mainbuffer.h"
33
32
#include "ringbuffer.h"
34
33
#include "sfl_types.h" // for SIZEBUF
35
36
#include <utility> // for std::pair
37
#include "scoped_lock.h"
36
38
#include "logger.h"
38
40
const char * const MainBuffer::DEFAULT_ID = "audiolayer_id";
40
42
MainBuffer::MainBuffer() : ringBufferMap_(), callIDMap_(), mutex_(), internalSamplingRate_(8000)
44
pthread_mutex_init(&mutex_, NULL);
43
47
MainBuffer::~MainBuffer()
45
49
// delete any ring buffers that didn't get removed
46
50
for (RingBufferMap::iterator iter = ringBufferMap_.begin(); iter != ringBufferMap_.end(); ++iter)
47
51
delete iter->second;
52
pthread_mutex_destroy(&mutex_);
50
55
void MainBuffer::setInternalSamplingRate(int sr)
58
CallIDSet* MainBuffer::getCallIDSet(const std::string & call_id)
63
CallIDSet* MainBuffer::getCallIDSet(const std::string &call_id)
60
65
CallIDMap::iterator iter = callIDMap_.find(call_id);
61
66
return (iter != callIDMap_.end()) ? iter->second : NULL;
64
void MainBuffer::createCallIDSet(const std::string & set_id)
66
callIDMap_.insert(std::pair<std::string, CallIDSet*> (set_id, new CallIDSet));
69
bool MainBuffer::removeCallIDSet(const std::string & set_id)
71
CallIDSet* callid_set = getCallIDSet(set_id);
74
DEBUG("CallID set %s does not exist!", set_id.c_str());
78
if (callIDMap_.erase(set_id) == 0) {
79
DEBUG("CallID set %s not found!", set_id.c_str());
88
void MainBuffer::addCallIDtoSet(const std::string & set_id, const std::string & call_id)
90
CallIDSet* callid_set = getCallIDSet(set_id);
91
callid_set->insert(call_id);
94
void MainBuffer::removeCallIDfromSet(const std::string & set_id, const std::string & call_id)
96
CallIDSet* callid_set = getCallIDSet(set_id);
98
if (callid_set == NULL)
99
ERROR("CallIDSet %s does not exist!", set_id.c_str());
100
else if (callid_set->erase(call_id) == 0)
101
ERROR("Could not find callID %s in set %s!", call_id.c_str(), set_id.c_str());
69
void MainBuffer::createCallIDSet(const std::string &set_id)
71
if (getCallIDSet(set_id) == NULL)
72
callIDMap_[set_id] = new CallIDSet;
74
DEBUG("CallID set %s already exists, ignoring", set_id.c_str());
77
void MainBuffer::removeCallIDSet(const std::string &set_id)
79
CallIDSet* callid_set = getCallIDSet(set_id);
82
callIDMap_.erase(set_id);
85
ERROR("CallID set %s does not exist!", set_id.c_str());
88
void MainBuffer::addCallIDtoSet(const std::string &set_id, const std::string &call_id)
90
CallIDSet* callid_set = getCallIDSet(set_id);
92
callid_set->insert(call_id);
94
ERROR("CallIDSet %s does not exist!", set_id.c_str());
97
void MainBuffer::removeCallIDfromSet(const std::string &set_id, const std::string &call_id)
99
CallIDSet* callid_set = getCallIDSet(set_id);
102
callid_set->erase(call_id);
104
ERROR("CallIDSet %s does not exist!", set_id.c_str());
104
107
RingBuffer* MainBuffer::getRingBuffer(const std::string & call_id)
107
110
return (iter != ringBufferMap_.end()) ? iter->second : NULL;
110
RingBuffer* MainBuffer::createRingBuffer(const std::string & call_id)
112
RingBuffer* newRingBuffer = new RingBuffer(SIZEBUF, call_id);
113
ringBufferMap_.insert(std::pair<std::string, RingBuffer*> (call_id, newRingBuffer));
114
return newRingBuffer;
117
bool MainBuffer::removeRingBuffer(const std::string & call_id)
113
const RingBuffer* MainBuffer::getRingBuffer(const std::string & call_id) const
115
RingBufferMap::const_iterator iter = ringBufferMap_.find(call_id);
116
return (iter != ringBufferMap_.end()) ? iter->second : NULL;
119
void MainBuffer::createRingBuffer(const std::string &call_id)
121
if (!getRingBuffer(call_id))
122
ringBufferMap_[call_id] = new RingBuffer(SIZEBUF, call_id);
124
DEBUG("Ringbuffer already exists for call_id %s", call_id.c_str());
127
void MainBuffer::removeRingBuffer(const std::string &call_id)
119
129
RingBuffer* ring_buffer = getRingBuffer(call_id);
121
if (ring_buffer != NULL) {
122
if (ringBufferMap_.erase(call_id) != 0) {
126
ERROR("Fail to delete ringbuffer %s!", call_id.c_str());
132
ringBufferMap_.erase(call_id);
130
135
DEBUG("Ringbuffer %s does not exist!", call_id.c_str());
135
138
void MainBuffer::bindCallID(const std::string & call_id1, const std::string & call_id2)
137
ost::MutexLock guard(mutex_);
139
if (getRingBuffer(call_id1) == NULL)
140
createRingBuffer(call_id1);
142
if (getCallIDSet(call_id1) == NULL)
143
createCallIDSet(call_id1);
145
if (getRingBuffer(call_id2) == NULL)
146
createRingBuffer(call_id2);
148
if (getCallIDSet(call_id2) == NULL)
149
createCallIDSet(call_id2);
140
sfl::ScopedLock guard(mutex_);
142
createRingBuffer(call_id1);
143
createCallIDSet(call_id1);
144
createRingBuffer(call_id2);
145
createCallIDSet(call_id2);
151
147
getRingBuffer(call_id1)->createReadPointer(call_id2);
152
148
getRingBuffer(call_id2)->createReadPointer(call_id1);
157
153
void MainBuffer::bindHalfDuplexOut(const std::string & process_id, const std::string & call_id)
159
ost::MutexLock guard(mutex_);
155
sfl::ScopedLock guard(mutex_);
161
157
// This method is used only for active calls, if this call does not exist, do nothing
162
158
if (!getRingBuffer(call_id))
165
if (!getCallIDSet(process_id))
166
createCallIDSet(process_id);
161
createCallIDSet(process_id);
168
162
getRingBuffer(call_id)->createReadPointer(process_id);
169
163
addCallIDtoSet(process_id, call_id);
172
166
void MainBuffer::unBindCallID(const std::string & call_id1, const std::string & call_id2)
174
ost::MutexLock guard(mutex_);
168
sfl::ScopedLock guard(mutex_);
176
170
removeCallIDfromSet(call_id1, call_id2);
177
171
removeCallIDfromSet(call_id2, call_id1);
244
void MainBuffer::putData(void *buffer, int toCopy, const std::string &call_id)
238
void MainBuffer::putData(void *buffer, size_t toCopy, const std::string &call_id)
246
ost::MutexLock guard(mutex_);
240
sfl::ScopedLock guard(mutex_);
248
242
RingBuffer* ring_buffer = getRingBuffer(call_id);
251
ring_buffer->Put(buffer, toCopy);
245
ring_buffer->put(buffer, toCopy);
254
int MainBuffer::getData(void *buffer, int toCopy, const std::string &call_id)
248
size_t MainBuffer::getData(void *buffer, size_t toCopy, const std::string &call_id)
256
ost::MutexLock guard(mutex_);
250
sfl::ScopedLock guard(mutex_);
258
252
CallIDSet* callid_set = getCallIDSet(call_id);
260
if (not callid_set or callid_set->empty())
254
if (callid_set == NULL or callid_set->empty())
263
257
if (callid_set->size() == 1) {
272
266
memset(buffer, 0, toCopy);
276
270
for (CallIDSet::iterator iter_id = callid_set->begin();
277
271
iter_id != callid_set->end(); ++iter_id) {
278
int nbSmplToCopy = toCopy / sizeof(SFLDataFormat);
272
size_t nbSmplToCopy = toCopy / sizeof(SFLDataFormat);
279
273
SFLDataFormat mixBuffer[nbSmplToCopy];
280
274
memset(mixBuffer, 0, toCopy);
281
275
size = getDataByID(mixBuffer, toCopy, *iter_id, call_id);
284
for (int k = 0; k < nbSmplToCopy; ++k)
285
((SFLDataFormat*)(buffer))[k] += mixBuffer[k];
278
SFLDataFormat *dest = static_cast<SFLDataFormat*>(buffer);
279
for (size_t k = 0; k < nbSmplToCopy; ++k)
280
dest[k] += mixBuffer[k];
293
int MainBuffer::getDataByID(void *buffer, int toCopy, const std::string & call_id, const std::string & reader_id)
288
size_t MainBuffer::getDataByID(void *buffer, size_t toCopy, const std::string & call_id, const std::string & reader_id)
295
290
RingBuffer* ring_buffer = getRingBuffer(call_id);
296
return ring_buffer ? ring_buffer->Get(buffer, toCopy, reader_id) : 0;
291
return ring_buffer ? ring_buffer->get(buffer, toCopy, reader_id) : 0;
299
int MainBuffer::availForGet(const std::string & call_id)
294
size_t MainBuffer::availableForGet(const std::string &call_id)
301
ost::MutexLock guard(mutex_);
296
sfl::ScopedLock guard(mutex_);
303
298
CallIDSet* callid_set = getCallIDSet(call_id);
305
if (callid_set == NULL)
308
if (callid_set->empty())
300
if (callid_set == NULL or callid_set->empty())
311
303
if (callid_set->size() == 1) {
312
304
CallIDSet::iterator iter_id = callid_set->begin();
314
306
if ((call_id != DEFAULT_ID) && (*iter_id == call_id))
315
DEBUG("This problem should not occur since we have %i element", (int) callid_set->size());
307
DEBUG("This problem should not occur since we have %ld elements", callid_set->size());
317
return availForGetByID(*iter_id, call_id);
309
return availableForGetByID(*iter_id, call_id);
321
int avail_bytes = 99999;
323
CallIDSet::iterator iter_id = callid_set->begin();
325
syncBuffers(call_id);
327
for (iter_id = callid_set->begin(); iter_id != callid_set->end(); ++iter_id) {
328
nb_bytes = availForGetByID(*iter_id, call_id);
330
if ((nb_bytes != 0) && (nb_bytes < avail_bytes))
331
avail_bytes = nb_bytes;
313
size_t availableBytes = INT_MAX;
314
for (CallIDSet::iterator i = callid_set->begin(); i != callid_set->end(); ++i) {
315
const size_t nbBytes = availableForGetByID(*i, call_id);
318
availableBytes = std::min(availableBytes, nbBytes);
334
return avail_bytes != 99999 ? avail_bytes : 0;
321
return availableBytes != INT_MAX ? availableBytes : 0;
338
int MainBuffer::availForGetByID(const std::string &call_id,
339
const std::string &reader_id)
325
size_t MainBuffer::availableForGetByID(const std::string &call_id,
326
const std::string &reader_id) const
341
if ((call_id != DEFAULT_ID) and (reader_id == call_id))
328
if (call_id != DEFAULT_ID and reader_id == call_id)
342
329
ERROR("RingBuffer has a readpointer on itself");
344
RingBuffer* ringbuffer = getRingBuffer(call_id);
331
const RingBuffer* ringbuffer = getRingBuffer(call_id);
346
333
if (ringbuffer == NULL) {
347
334
ERROR("RingBuffer does not exist");
350
return ringbuffer->AvailForGet(reader_id);
337
return ringbuffer->availableForGet(reader_id);
354
int MainBuffer::discard(int toDiscard, const std::string &call_id)
341
size_t MainBuffer::discard(size_t toDiscard, const std::string &call_id)
356
ost::MutexLock guard(mutex_);
343
sfl::ScopedLock guard(mutex_);
358
345
CallIDSet* callid_set = getCallIDSet(call_id);
366
353
return toDiscard;
369
void MainBuffer::discardByID(int toDiscard, const std::string & call_id, const std::string & reader_id)
356
void MainBuffer::discardByID(size_t toDiscard, const std::string & call_id, const std::string & reader_id)
371
358
RingBuffer* ringbuffer = getRingBuffer(call_id);
374
ringbuffer->Discard(toDiscard, reader_id);
361
ringbuffer->discard(toDiscard, reader_id);
377
364
void MainBuffer::flush(const std::string & call_id)
379
ost::MutexLock guard(mutex_);
366
sfl::ScopedLock guard(mutex_);
381
368
CallIDSet* callid_set = getCallIDSet(call_id);
403
390
iter->second->flushAll();
406
void MainBuffer::syncBuffers(const std::string & call_id)
408
CallIDSet* callid_set = getCallIDSet(call_id);
410
if (callid_set || callid_set->empty())
413
if (callid_set->size() == 1) // no need to resync, only one session
416
float mean_nbBytes = 0.0;
418
// compute mean nb byte in buffers
420
for (CallIDSet::iterator iter = callid_set->begin();
421
iter != callid_set->end(); ++iter)
422
mean_nbBytes += availForGetByID(*iter, call_id);
424
mean_nbBytes /= static_cast<float>(callid_set->size());
426
// resync buffers in this conference according to the computed mean
427
for (CallIDSet::iterator iter = callid_set->begin();
428
iter != callid_set->end(); ++iter)
429
if (availForGetByID(*iter, call_id) > (mean_nbBytes + 640))
430
discardByID(640, *iter, call_id);
433
void MainBuffer::stateInfo()
393
void MainBuffer::dumpInfo()
395
sfl::ScopedLock guard(mutex_);
435
396
// print each call and bound call ids
436
for (CallIDMap::iterator iter_call = callIDMap_.begin(); iter_call != callIDMap_.end(); ++iter_call) {
397
for (CallIDMap::const_iterator iter_call = callIDMap_.begin(); iter_call != callIDMap_.end(); ++iter_call) {
437
398
std::string dbg_str(" Call: \t");
438
399
dbg_str.append(iter_call->first);
439
400
dbg_str.append(" is bound to: \t");
451
412
// Print ringbuffers ids and readpointers
452
for (RingBufferMap::iterator iter_buffer = ringBufferMap_.begin(); iter_buffer != ringBufferMap_.end(); ++iter_buffer) {
453
RingBuffer* rbuffer = iter_buffer->second;
454
ReadPointer* rpointer = NULL;
413
for (RingBufferMap::const_iterator iter_buffer = ringBufferMap_.begin(); iter_buffer != ringBufferMap_.end(); ++iter_buffer) {
456
414
std::string dbg_str(" Buffer: \t");
458
416
dbg_str.append(iter_buffer->first);
459
417
dbg_str.append(" as read pointer: \t");
462
rpointer = rbuffer->getReadPointerList();
419
RingBuffer* rbuffer = iter_buffer->second;
421
ReadPointer* rpointer = rbuffer->getReadPointerList();
465
for (ReadPointer::iterator iter = rpointer->begin(); iter != rpointer->end(); ++iter) {
466
dbg_str.append(iter->first);
467
dbg_str.append(", ");
424
for (ReadPointer::iterator iter = rpointer->begin(); iter != rpointer->end(); ++iter) {
425
dbg_str.append(iter->first);
426
dbg_str.append(", ");
470
430
DEBUG("%s", dbg_str.c_str());