~ubuntu-branches/ubuntu/trusty/sflphone/trusty

« back to all changes in this revision

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

  • Committer: Package Import Robot
  • Author(s): Mark Purcell
  • Date: 2014-01-28 18:23:36 UTC
  • mfrom: (4.3.4 sid)
  • Revision ID: package-import@ubuntu.com-20140128182336-jrsv0k9u6cawc068
Tags: 1.3.0-1
* New upstream release 
  - Fixes "New Upstream Release" (Closes: #735846)
  - Fixes "Ringtone does not stop" (Closes: #727164)
  - Fixes "[sflphone-kde] crash on startup" (Closes: #718178)
  - Fixes "sflphone GUI crashes when call is hung up" (Closes: #736583)
* Build-Depends: ensure GnuTLS 2.6
  - libucommon-dev (>= 6.0.7-1.1), libccrtp-dev (>= 2.0.6-3)
  - Fixes "FTBFS Build-Depends libgnutls{26,28}-dev" (Closes: #722040)
* Fix "boost 1.49 is going away" unversioned Build-Depends: (Closes: #736746)
* Add Build-Depends: libsndfile-dev, nepomuk-core-dev

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
 
 *  Copyright (C) 2004-2012 Savoir-Faire Linux Inc.
 
2
 *  Copyright (C) 2004-2013 Savoir-Faire Linux Inc.
3
3
 *  Author : Alexandre Savard <alexandre.savard@savoirfairelinux.com>
4
4
 *
5
5
 *  This program is free software; you can redistribute it and/or modify
31
31
#include "mainbuffer.h"
32
32
#include "ringbuffer.h"
33
33
#include "sfl_types.h" // for SIZEBUF
34
 
#include <climits>
 
34
#include <limits>
35
35
#include <cstring>
36
36
#include <utility> // for std::pair
37
 
#include "scoped_lock.h"
38
37
#include "logger.h"
39
38
 
40
39
const char * const MainBuffer::DEFAULT_ID = "audiolayer_id";
41
40
 
42
41
MainBuffer::MainBuffer() : ringBufferMap_(), callIDMap_(), mutex_(), internalSamplingRate_(8000)
43
 
{
44
 
    pthread_mutex_init(&mutex_, NULL);
45
 
}
 
42
{}
46
43
 
47
44
MainBuffer::~MainBuffer()
48
45
{
49
46
    // delete any ring buffers that didn't get removed
50
 
    for (RingBufferMap::iterator iter = ringBufferMap_.begin(); iter != ringBufferMap_.end(); ++iter)
51
 
        delete iter->second;
52
 
    pthread_mutex_destroy(&mutex_);
 
47
    for (auto &item : ringBufferMap_)
 
48
        delete item.second;
53
49
}
54
50
 
55
51
void MainBuffer::setInternalSamplingRate(int sr)
56
52
{
57
 
    if (sr > internalSamplingRate_) {
 
53
    if (sr != internalSamplingRate_) {
58
54
        flushAllBuffers();
59
55
        internalSamplingRate_ = sr;
60
56
    }
88
84
void MainBuffer::addCallIDtoSet(const std::string &set_id, const std::string &call_id)
89
85
{
90
86
    CallIDSet* callid_set = getCallIDSet(set_id);
 
87
 
91
88
    if (callid_set)
92
89
        callid_set->insert(call_id);
93
90
    else
137
134
 
138
135
void MainBuffer::bindCallID(const std::string & call_id1, const std::string & call_id2)
139
136
{
140
 
    sfl::ScopedLock guard(mutex_);
 
137
    std::lock_guard<std::mutex> guard(mutex_);
141
138
 
142
139
    createRingBuffer(call_id1);
143
140
    createCallIDSet(call_id1);
152
149
 
153
150
void MainBuffer::bindHalfDuplexOut(const std::string & process_id, const std::string & call_id)
154
151
{
155
 
    sfl::ScopedLock guard(mutex_);
 
152
    std::lock_guard<std::mutex> guard(mutex_);
156
153
 
157
154
    // This method is used only for active calls, if this call does not exist, do nothing
158
155
    if (!getRingBuffer(call_id))
165
162
 
166
163
void MainBuffer::unBindCallID(const std::string & call_id1, const std::string & call_id2)
167
164
{
168
 
    sfl::ScopedLock guard(mutex_);
 
165
    std::lock_guard<std::mutex> guard(mutex_);
169
166
 
170
167
    removeCallIDfromSet(call_id1, call_id2);
171
168
    removeCallIDfromSet(call_id2, call_id1);
195
192
 
196
193
void MainBuffer::unBindHalfDuplexOut(const std::string & process_id, const std::string & call_id)
197
194
{
198
 
    sfl::ScopedLock guard(mutex_);
 
195
    std::lock_guard<std::mutex> guard(mutex_);
199
196
 
200
197
    removeCallIDfromSet(process_id, call_id);
201
198
 
228
225
 
229
226
    CallIDSet temp_set(*callid_set);
230
227
 
231
 
    for (CallIDSet::iterator iter_set = temp_set.begin();
232
 
         iter_set != temp_set.end(); ++iter_set) {
233
 
        std::string call_id_in_set(*iter_set);
234
 
        unBindCallID(call_id, call_id_in_set);
235
 
    }
 
228
    for (const auto &item_set : temp_set)
 
229
        unBindCallID(call_id, item_set);
236
230
}
237
231
 
238
 
void MainBuffer::putData(void *buffer, size_t toCopy, const std::string &call_id)
 
232
void MainBuffer::putData(AudioBuffer& buffer, const std::string &call_id)
239
233
{
240
 
    sfl::ScopedLock guard(mutex_);
 
234
    std::lock_guard<std::mutex> guard(mutex_);
241
235
 
242
236
    RingBuffer* ring_buffer = getRingBuffer(call_id);
243
237
 
244
238
    if (ring_buffer)
245
 
        ring_buffer->put(buffer, toCopy);
 
239
        ring_buffer->put(buffer);
246
240
}
247
241
 
248
 
size_t MainBuffer::getData(void *buffer, size_t toCopy, const std::string &call_id)
 
242
size_t MainBuffer::getData(AudioBuffer& buffer, const std::string &call_id)
249
243
{
250
 
    sfl::ScopedLock guard(mutex_);
 
244
    std::lock_guard<std::mutex> guard(mutex_);
251
245
 
252
246
    CallIDSet* callid_set = getCallIDSet(call_id);
253
247
 
259
253
        CallIDSet::iterator iter_id = callid_set->begin();
260
254
 
261
255
        if (iter_id != callid_set->end())
262
 
            return getDataByID(buffer, toCopy, *iter_id, call_id);
 
256
            return getDataByID(buffer, *iter_id, call_id);
263
257
        else
264
258
            return 0;
265
259
    } else {
266
 
        memset(buffer, 0, toCopy);
 
260
        buffer.reset();
 
261
        buffer.setSampleRate(internalSamplingRate_);
267
262
 
268
263
        size_t size = 0;
 
264
        AudioBuffer mixBuffer(buffer);
269
265
 
270
 
        for (CallIDSet::iterator iter_id = callid_set->begin();
271
 
             iter_id != callid_set->end(); ++iter_id) {
272
 
            size_t nbSmplToCopy = toCopy / sizeof(SFLDataFormat);
273
 
            SFLDataFormat mixBuffer[nbSmplToCopy];
274
 
            memset(mixBuffer, 0, toCopy);
275
 
            size = getDataByID(mixBuffer, toCopy, *iter_id, call_id);
 
266
        for (const auto &item_id : *callid_set) {
 
267
            size = getDataByID(mixBuffer, item_id, call_id);
276
268
 
277
269
            if (size > 0) {
278
 
                SFLDataFormat *dest = static_cast<SFLDataFormat*>(buffer);
279
 
                for (size_t k = 0; k < nbSmplToCopy; ++k)
280
 
                    dest[k] += mixBuffer[k];
 
270
                buffer.mix(mixBuffer);
281
271
            }
282
272
        }
283
273
 
285
275
    }
286
276
}
287
277
 
288
 
size_t MainBuffer::getDataByID(void *buffer, size_t toCopy, const std::string & call_id, const std::string & reader_id)
 
278
size_t MainBuffer::getDataByID(AudioBuffer& buffer, const std::string & call_id, const std::string & reader_id)
289
279
{
290
280
    RingBuffer* ring_buffer = getRingBuffer(call_id);
291
 
    return ring_buffer ? ring_buffer->get(buffer, toCopy, reader_id) : 0;
 
281
    return ring_buffer ? ring_buffer->get(buffer, reader_id) : 0;
292
282
}
293
283
 
294
284
size_t MainBuffer::availableForGet(const std::string &call_id)
295
285
{
296
 
    sfl::ScopedLock guard(mutex_);
 
286
    std::lock_guard<std::mutex> guard(mutex_);
297
287
 
298
288
    CallIDSet* callid_set = getCallIDSet(call_id);
299
289
 
310
300
 
311
301
    } else {
312
302
 
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);
 
303
        size_t availableSamples = std::numeric_limits<size_t>::max();
 
304
 
 
305
        for (auto &i : *callid_set) {
 
306
            const size_t nbSamples = availableForGetByID(i, call_id);
 
307
 
 
308
            if (nbSamples != 0)
 
309
                availableSamples = std::min(availableSamples, nbSamples);
319
310
        }
320
311
 
321
 
        return availableBytes != INT_MAX ? availableBytes : 0;
 
312
        return availableSamples != std::numeric_limits<size_t>::max() ? availableSamples : 0;
322
313
    }
323
314
}
324
315
 
325
316
size_t MainBuffer::availableForGetByID(const std::string &call_id,
326
 
                                const std::string &reader_id) const
 
317
                                       const std::string &reader_id) const
327
318
{
328
319
    if (call_id != DEFAULT_ID and reader_id == call_id)
329
320
        ERROR("RingBuffer has a readpointer on itself");
340
331
 
341
332
size_t MainBuffer::discard(size_t toDiscard, const std::string &call_id)
342
333
{
343
 
    sfl::ScopedLock guard(mutex_);
 
334
    std::lock_guard<std::mutex> guard(mutex_);
344
335
 
345
336
    CallIDSet* callid_set = getCallIDSet(call_id);
346
337
 
347
338
    if (!callid_set or callid_set->empty())
348
339
        return 0;
349
340
 
350
 
    for (CallIDSet::iterator iter = callid_set->begin(); iter != callid_set->end(); ++iter)
351
 
        discardByID(toDiscard, *iter, call_id);
 
341
    for (auto &item : *callid_set)
 
342
        discardByID(toDiscard, item, call_id);
352
343
 
353
344
    return toDiscard;
354
345
}
363
354
 
364
355
void MainBuffer::flush(const std::string & call_id)
365
356
{
366
 
    sfl::ScopedLock guard(mutex_);
 
357
    std::lock_guard<std::mutex> guard(mutex_);
367
358
 
368
359
    CallIDSet* callid_set = getCallIDSet(call_id);
369
360
 
370
361
    if (callid_set == NULL)
371
362
        return;
372
363
 
373
 
    for (CallIDSet::iterator iter = callid_set->begin(); iter != callid_set->end(); ++iter)
374
 
        flushByID(*iter, call_id);
375
 
 
 
364
    for (auto &item : *callid_set)
 
365
        flushByID(item, call_id);
376
366
}
377
367
 
378
368
void MainBuffer::flushByID(const std::string & call_id, const std::string & reader_id)
386
376
 
387
377
void MainBuffer::flushAllBuffers()
388
378
{
389
 
    for (RingBufferMap::iterator iter = ringBufferMap_.begin(); iter != ringBufferMap_.end(); ++iter)
390
 
        iter->second->flushAll();
391
 
}
392
 
 
393
 
void MainBuffer::dumpInfo()
394
 
{
395
 
    sfl::ScopedLock guard(mutex_);
396
 
    // print each call and bound call ids
397
 
    for (CallIDMap::const_iterator iter_call = callIDMap_.begin(); iter_call != callIDMap_.end(); ++iter_call) {
398
 
        std::string dbg_str("    Call: \t");
399
 
        dbg_str.append(iter_call->first);
400
 
        dbg_str.append("   is bound to: \t");
401
 
 
402
 
        CallIDSet *call_id_set = iter_call->second;
403
 
 
404
 
        for (CallIDSet::iterator iter = call_id_set->begin(); iter != call_id_set->end(); ++iter) {
405
 
            dbg_str.append(*iter);
406
 
            dbg_str.append(", ");
407
 
        }
408
 
 
409
 
        DEBUG("%s", dbg_str.c_str());
410
 
    }
411
 
 
412
 
    // Print ringbuffers ids and readpointers
413
 
    for (RingBufferMap::const_iterator iter_buffer = ringBufferMap_.begin(); iter_buffer != ringBufferMap_.end(); ++iter_buffer) {
414
 
        std::string dbg_str("    Buffer: \t");
415
 
 
416
 
        dbg_str.append(iter_buffer->first);
417
 
        dbg_str.append("   as read pointer: \t");
418
 
 
419
 
        RingBuffer* rbuffer = iter_buffer->second;
420
 
        if (rbuffer) {
421
 
            ReadPointer* rpointer = rbuffer->getReadPointerList();
422
 
 
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
 
                }
428
 
            }
429
 
        }
430
 
        DEBUG("%s", dbg_str.c_str());
431
 
    }
 
379
    for (auto &item : ringBufferMap_)
 
380
        item.second->flushAll();
432
381
}