~ubuntu-branches/ubuntu/utopic/sflphone/utopic-proposed

« back to all changes in this revision

Viewing changes to daemon/src/audio/mainbuffer.cpp

  • Committer: Package Import Robot
  • Author(s): Mark Purcell
  • Date: 2013-06-30 11:40:56 UTC
  • mfrom: (4.1.18 saucy-proposed)
  • Revision ID: package-import@ubuntu.com-20130630114056-0np50jkyqo6vnmii
Tags: 1.2.3-2
* changeset_r92d62cfc54732bbbcfff2b1d36c096b120b981a5.diff 
  - fixes automatic endian detection 
* Update Vcs: fixes vcs-field-not-canonical

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
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>
4
4
 *
5
 
 *
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
15
14
 *
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.
19
18
 *
20
19
 *  Additional permission under GNU GPL version 3 section 7:
21
20
 *
32
31
#include "mainbuffer.h"
33
32
#include "ringbuffer.h"
34
33
#include "sfl_types.h" // for SIZEBUF
 
34
#include <climits>
 
35
#include <cstring>
35
36
#include <utility> // for std::pair
 
37
#include "scoped_lock.h"
36
38
#include "logger.h"
37
39
 
38
40
const char * const MainBuffer::DEFAULT_ID = "audiolayer_id";
39
41
 
40
42
MainBuffer::MainBuffer() : ringBufferMap_(), callIDMap_(), mutex_(), internalSamplingRate_(8000)
41
 
{}
 
43
{
 
44
    pthread_mutex_init(&mutex_, NULL);
 
45
}
42
46
 
43
47
MainBuffer::~MainBuffer()
44
48
{
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_);
48
53
}
49
54
 
50
55
void MainBuffer::setInternalSamplingRate(int sr)
55
60
    }
56
61
}
57
62
 
58
 
CallIDSet* MainBuffer::getCallIDSet(const std::string & call_id)
 
63
CallIDSet* MainBuffer::getCallIDSet(const std::string &call_id)
59
64
{
60
65
    CallIDMap::iterator iter = callIDMap_.find(call_id);
61
66
    return (iter != callIDMap_.end()) ? iter->second : NULL;
62
67
}
63
68
 
64
 
void MainBuffer::createCallIDSet(const std::string & set_id)
65
 
{
66
 
    callIDMap_.insert(std::pair<std::string, CallIDSet*> (set_id, new CallIDSet));
67
 
}
68
 
 
69
 
bool MainBuffer::removeCallIDSet(const std::string & set_id)
70
 
{
71
 
    CallIDSet* callid_set = getCallIDSet(set_id);
72
 
 
73
 
    if (!callid_set) {
74
 
        DEBUG("CallID set %s does not exist!", set_id.c_str());
75
 
        return false;
76
 
    }
77
 
 
78
 
    if (callIDMap_.erase(set_id) == 0) {
79
 
        DEBUG("CallID set %s not found!", set_id.c_str());
80
 
        return false;
81
 
    }
82
 
 
83
 
    delete callid_set;
84
 
    callid_set = NULL;
85
 
    return true;
86
 
}
87
 
 
88
 
void MainBuffer::addCallIDtoSet(const std::string & set_id, const std::string & call_id)
89
 
{
90
 
    CallIDSet* callid_set = getCallIDSet(set_id);
91
 
    callid_set->insert(call_id);
92
 
}
93
 
 
94
 
void MainBuffer::removeCallIDfromSet(const std::string & set_id, const std::string & call_id)
95
 
{
96
 
    CallIDSet* callid_set = getCallIDSet(set_id);
97
 
 
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)
 
70
{
 
71
    if (getCallIDSet(set_id) == NULL)
 
72
        callIDMap_[set_id] = new CallIDSet;
 
73
    else
 
74
        DEBUG("CallID set %s already exists, ignoring", set_id.c_str());
 
75
}
 
76
 
 
77
void MainBuffer::removeCallIDSet(const std::string &set_id)
 
78
{
 
79
    CallIDSet* callid_set = getCallIDSet(set_id);
 
80
 
 
81
    if (callid_set) {
 
82
        callIDMap_.erase(set_id);
 
83
        delete callid_set;
 
84
    } else
 
85
        ERROR("CallID set %s does not exist!", set_id.c_str());
 
86
}
 
87
 
 
88
void MainBuffer::addCallIDtoSet(const std::string &set_id, const std::string &call_id)
 
89
{
 
90
    CallIDSet* callid_set = getCallIDSet(set_id);
 
91
    if (callid_set)
 
92
        callid_set->insert(call_id);
 
93
    else
 
94
        ERROR("CallIDSet %s does not exist!", set_id.c_str());
 
95
}
 
96
 
 
97
void MainBuffer::removeCallIDfromSet(const std::string &set_id, const std::string &call_id)
 
98
{
 
99
    CallIDSet* callid_set = getCallIDSet(set_id);
 
100
 
 
101
    if (callid_set)
 
102
        callid_set->erase(call_id);
 
103
    else
 
104
        ERROR("CallIDSet %s does not exist!", set_id.c_str());
102
105
}
103
106
 
104
107
RingBuffer* MainBuffer::getRingBuffer(const std::string & call_id)
107
110
    return (iter != ringBufferMap_.end()) ? iter->second : NULL;
108
111
}
109
112
 
110
 
RingBuffer* MainBuffer::createRingBuffer(const std::string & call_id)
111
 
{
112
 
    RingBuffer* newRingBuffer = new RingBuffer(SIZEBUF, call_id);
113
 
    ringBufferMap_.insert(std::pair<std::string, RingBuffer*> (call_id, newRingBuffer));
114
 
    return newRingBuffer;
115
 
}
116
 
 
117
 
bool MainBuffer::removeRingBuffer(const std::string & call_id)
 
113
const RingBuffer* MainBuffer::getRingBuffer(const std::string & call_id) const
 
114
{
 
115
    RingBufferMap::const_iterator iter = ringBufferMap_.find(call_id);
 
116
    return (iter != ringBufferMap_.end()) ? iter->second : NULL;
 
117
}
 
118
 
 
119
void MainBuffer::createRingBuffer(const std::string &call_id)
 
120
{
 
121
    if (!getRingBuffer(call_id))
 
122
        ringBufferMap_[call_id] = new RingBuffer(SIZEBUF, call_id);
 
123
    else
 
124
        DEBUG("Ringbuffer already exists for call_id %s", call_id.c_str());
 
125
}
 
126
 
 
127
void MainBuffer::removeRingBuffer(const std::string &call_id)
118
128
{
119
129
    RingBuffer* ring_buffer = getRingBuffer(call_id);
120
130
 
121
 
    if (ring_buffer != NULL) {
122
 
        if (ringBufferMap_.erase(call_id) != 0) {
123
 
            delete ring_buffer;
124
 
            return true;
125
 
        } else {
126
 
            ERROR("Fail to delete ringbuffer %s!", call_id.c_str());
127
 
            return false;
128
 
        }
129
 
    } else {
 
131
    if (ring_buffer) {
 
132
        ringBufferMap_.erase(call_id);
 
133
        delete ring_buffer;
 
134
    } else
130
135
        DEBUG("Ringbuffer %s does not exist!", call_id.c_str());
131
 
        return true;
132
 
    }
133
136
}
134
137
 
135
138
void MainBuffer::bindCallID(const std::string & call_id1, const std::string & call_id2)
136
139
{
137
 
    ost::MutexLock guard(mutex_);
138
 
 
139
 
    if (getRingBuffer(call_id1) == NULL)
140
 
        createRingBuffer(call_id1);
141
 
 
142
 
    if (getCallIDSet(call_id1) == NULL)
143
 
        createCallIDSet(call_id1);
144
 
 
145
 
    if (getRingBuffer(call_id2) == NULL)
146
 
        createRingBuffer(call_id2);
147
 
 
148
 
    if (getCallIDSet(call_id2) == NULL)
149
 
        createCallIDSet(call_id2);
 
140
    sfl::ScopedLock guard(mutex_);
 
141
 
 
142
    createRingBuffer(call_id1);
 
143
    createCallIDSet(call_id1);
 
144
    createRingBuffer(call_id2);
 
145
    createCallIDSet(call_id2);
150
146
 
151
147
    getRingBuffer(call_id1)->createReadPointer(call_id2);
152
148
    getRingBuffer(call_id2)->createReadPointer(call_id1);
156
152
 
157
153
void MainBuffer::bindHalfDuplexOut(const std::string & process_id, const std::string & call_id)
158
154
{
159
 
    ost::MutexLock guard(mutex_);
 
155
    sfl::ScopedLock guard(mutex_);
160
156
 
161
157
    // This method is used only for active calls, if this call does not exist, do nothing
162
158
    if (!getRingBuffer(call_id))
163
159
        return;
164
160
 
165
 
    if (!getCallIDSet(process_id))
166
 
        createCallIDSet(process_id);
167
 
 
 
161
    createCallIDSet(process_id);
168
162
    getRingBuffer(call_id)->createReadPointer(process_id);
169
163
    addCallIDtoSet(process_id, call_id);
170
164
}
171
165
 
172
166
void MainBuffer::unBindCallID(const std::string & call_id1, const std::string & call_id2)
173
167
{
174
 
    ost::MutexLock guard(mutex_);
 
168
    sfl::ScopedLock guard(mutex_);
175
169
 
176
170
    removeCallIDfromSet(call_id1, call_id2);
177
171
    removeCallIDfromSet(call_id2, call_id1);
181
175
    if (ringbuffer) {
182
176
        ringbuffer->removeReadPointer(call_id1);
183
177
 
184
 
        if (ringbuffer->getNbReadPointer() == 0) {
 
178
        if (ringbuffer->hasNoReadPointers()) {
185
179
            removeCallIDSet(call_id2);
186
180
            removeRingBuffer(call_id2);
187
181
        }
192
186
    if (ringbuffer) {
193
187
        ringbuffer->removeReadPointer(call_id2);
194
188
 
195
 
        if (ringbuffer->getNbReadPointer() == 0) {
 
189
        if (ringbuffer->hasNoReadPointers()) {
196
190
            removeCallIDSet(call_id1);
197
191
            removeRingBuffer(call_id1);
198
192
        }
201
195
 
202
196
void MainBuffer::unBindHalfDuplexOut(const std::string & process_id, const std::string & call_id)
203
197
{
204
 
    ost::MutexLock guard(mutex_);
 
198
    sfl::ScopedLock guard(mutex_);
205
199
 
206
200
    removeCallIDfromSet(process_id, call_id);
207
201
 
210
204
    if (ringbuffer) {
211
205
        ringbuffer->removeReadPointer(process_id);
212
206
 
213
 
        if (ringbuffer->getNbReadPointer() == 0) {
 
207
        if (ringbuffer->hasNoReadPointers()) {
214
208
            removeCallIDSet(call_id);
215
209
            removeRingBuffer(call_id);
216
210
        }
241
235
    }
242
236
}
243
237
 
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)
245
239
{
246
 
    ost::MutexLock guard(mutex_);
 
240
    sfl::ScopedLock guard(mutex_);
247
241
 
248
242
    RingBuffer* ring_buffer = getRingBuffer(call_id);
249
243
 
250
244
    if (ring_buffer)
251
 
        ring_buffer->Put(buffer, toCopy);
 
245
        ring_buffer->put(buffer, toCopy);
252
246
}
253
247
 
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)
255
249
{
256
 
    ost::MutexLock guard(mutex_);
 
250
    sfl::ScopedLock guard(mutex_);
257
251
 
258
252
    CallIDSet* callid_set = getCallIDSet(call_id);
259
253
 
260
 
    if (not callid_set or callid_set->empty())
 
254
    if (callid_set == NULL or callid_set->empty())
261
255
        return 0;
262
256
 
263
257
    if (callid_set->size() == 1) {
271
265
    } else {
272
266
        memset(buffer, 0, toCopy);
273
267
 
274
 
        int size = 0;
 
268
        size_t size = 0;
275
269
 
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);
282
276
 
283
277
            if (size > 0) {
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];
286
281
            }
287
282
        }
288
283
 
290
285
    }
291
286
}
292
287
 
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)
294
289
{
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;
297
292
}
298
293
 
299
 
int MainBuffer::availForGet(const std::string & call_id)
 
294
size_t MainBuffer::availableForGet(const std::string &call_id)
300
295
{
301
 
    ost::MutexLock guard(mutex_);
 
296
    sfl::ScopedLock guard(mutex_);
302
297
 
303
298
    CallIDSet* callid_set = getCallIDSet(call_id);
304
299
 
305
 
    if (callid_set == NULL)
306
 
        return 0;
307
 
 
308
 
    if (callid_set->empty())
 
300
    if (callid_set == NULL or callid_set->empty())
309
301
        return 0;
310
302
 
311
303
    if (callid_set->size() == 1) {
312
304
        CallIDSet::iterator iter_id = callid_set->begin();
313
305
 
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());
316
308
 
317
 
        return availForGetByID(*iter_id, call_id);
 
309
        return availableForGetByID(*iter_id, call_id);
318
310
 
319
311
    } else {
320
312
 
321
 
        int avail_bytes = 99999;
322
 
        int nb_bytes;
323
 
        CallIDSet::iterator iter_id = callid_set->begin();
324
 
 
325
 
        syncBuffers(call_id);
326
 
 
327
 
        for (iter_id = callid_set->begin(); iter_id != callid_set->end(); ++iter_id) {
328
 
            nb_bytes = availForGetByID(*iter_id, call_id);
329
 
 
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);
 
316
 
 
317
            if (nbBytes != 0)
 
318
                availableBytes = std::min(availableBytes, nbBytes);
332
319
        }
333
320
 
334
 
        return avail_bytes != 99999 ? avail_bytes : 0;
 
321
        return availableBytes != INT_MAX ? availableBytes : 0;
335
322
    }
336
323
}
337
324
 
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
340
327
{
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");
343
330
 
344
 
    RingBuffer* ringbuffer = getRingBuffer(call_id);
 
331
    const RingBuffer* ringbuffer = getRingBuffer(call_id);
345
332
 
346
333
    if (ringbuffer == NULL) {
347
334
        ERROR("RingBuffer does not exist");
348
335
        return 0;
349
336
    } else
350
 
        return ringbuffer->AvailForGet(reader_id);
 
337
        return ringbuffer->availableForGet(reader_id);
351
338
 
352
339
}
353
340
 
354
 
int MainBuffer::discard(int toDiscard, const std::string &call_id)
 
341
size_t MainBuffer::discard(size_t toDiscard, const std::string &call_id)
355
342
{
356
 
    ost::MutexLock guard(mutex_);
 
343
    sfl::ScopedLock guard(mutex_);
357
344
 
358
345
    CallIDSet* callid_set = getCallIDSet(call_id);
359
346
 
366
353
    return toDiscard;
367
354
}
368
355
 
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)
370
357
{
371
358
    RingBuffer* ringbuffer = getRingBuffer(call_id);
372
359
 
373
360
    if (ringbuffer)
374
 
        ringbuffer->Discard(toDiscard, reader_id);
 
361
        ringbuffer->discard(toDiscard, reader_id);
375
362
}
376
363
 
377
364
void MainBuffer::flush(const std::string & call_id)
378
365
{
379
 
    ost::MutexLock guard(mutex_);
 
366
    sfl::ScopedLock guard(mutex_);
380
367
 
381
368
    CallIDSet* callid_set = getCallIDSet(call_id);
382
369
 
392
379
{
393
380
    RingBuffer* ringbuffer = getRingBuffer(call_id);
394
381
 
395
 
    if (ringbuffer != NULL)
 
382
    if (ringbuffer)
396
383
        ringbuffer->flush(reader_id);
397
384
}
398
385
 
403
390
        iter->second->flushAll();
404
391
}
405
392
 
406
 
void MainBuffer::syncBuffers(const std::string & call_id)
407
 
{
408
 
    CallIDSet* callid_set = getCallIDSet(call_id);
409
 
 
410
 
    if (callid_set || callid_set->empty())
411
 
        return;
412
 
 
413
 
    if (callid_set->size() == 1) // no need to resync, only one session
414
 
        return;
415
 
 
416
 
    float mean_nbBytes = 0.0;
417
 
 
418
 
    // compute mean nb byte in buffers
419
 
 
420
 
    for (CallIDSet::iterator iter = callid_set->begin();
421
 
         iter != callid_set->end(); ++iter)
422
 
        mean_nbBytes += availForGetByID(*iter, call_id);
423
 
 
424
 
    mean_nbBytes /= static_cast<float>(callid_set->size());
425
 
 
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);
431
 
}
432
 
 
433
 
void MainBuffer::stateInfo()
434
 
{
 
393
void MainBuffer::dumpInfo()
 
394
{
 
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");
449
410
    }
450
411
 
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;
455
 
 
 
413
    for (RingBufferMap::const_iterator iter_buffer = ringBufferMap_.begin(); iter_buffer != ringBufferMap_.end(); ++iter_buffer) {
456
414
        std::string dbg_str("    Buffer: \t");
457
415
 
458
416
        dbg_str.append(iter_buffer->first);
459
417
        dbg_str.append("   as read pointer: \t");
460
418
 
461
 
        if (rbuffer)
462
 
            rpointer = rbuffer->getReadPointerList();
 
419
        RingBuffer* rbuffer = iter_buffer->second;
 
420
        if (rbuffer) {
 
421
            ReadPointer* rpointer = rbuffer->getReadPointerList();
463
422
 
464
 
        if (rpointer) {
465
 
            for (ReadPointer::iterator iter = rpointer->begin(); iter != rpointer->end(); ++iter) {
466
 
                dbg_str.append(iter->first);
467
 
                dbg_str.append(", ");
 
423
            if (rpointer) {
 
424
                for (ReadPointer::iterator iter = rpointer->begin(); iter != rpointer->end(); ++iter) {
 
425
                    dbg_str.append(iter->first);
 
426
                    dbg_str.append(", ");
 
427
                }
468
428
            }
469
429
        }
470
430
        DEBUG("%s", dbg_str.c_str());