audio_rtp_record_handler.cpp 13.3 KB
Newer Older
1
/*
2
 *  Copyright (C) 2004-2013 Savoir-Faire Linux Inc.
3
 *  Author: Alexandre Savard <alexandre.savard@savoirfairelinux.com>
Adrien Béraud's avatar
Adrien Béraud committed
4
 *  Author: Adrien Beraud <adrien.beraud@wisdomvibes.com>
5 6 7 8 9 10 11 12 13 14 15 16
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 3 of the License, or
 *  (at your option) any later version.
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
17
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.
18 19 20 21 22 23 24 25 26 27 28 29 30
 *
 *  Additional permission under GNU GPL version 3 section 7:
 *
 *  If you modify this program, or any covered work, by linking or
 *  combining it with the OpenSSL project's OpenSSL library (or a
 *  modified version of that library), containing parts covered by the
 *  terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc.
 *  grants you additional permission to convey the resulting work.
 *  Corresponding Source for a non-source form of such a combination
 *  shall include the source code for the parts of OpenSSL used as well
 *  as that of the covered work.
 */

31 32 33 34
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

35
#include "audio_rtp_record_handler.h"
36
#include <fstream>
37
#include <algorithm>
38
#include "logger.h"
Rafaël Carré's avatar
Rafaël Carré committed
39
#include "sip/sipcall.h"
40 41 42
#include "audio/audiolayer.h"
#include "manager.h"

43
namespace sfl {
44

45
#ifdef RECTODISK
46
std::ofstream rtpResampled("testRtpOutputResampled.raw", std::ifstream::binary);
47 48 49
std::ofstream rtpNotResampled("testRtpOutput.raw", std::ifstream::binary);
#endif

50
DTMFEvent::DTMFEvent(char digit) : payload(), newevent(true), length(1000)
51
{
52 53 54 55 56 57 58 59 60 61 62
    /*
       From RFC2833:

       Event  encoding (decimal)
       _________________________
       0--9                0--9
       *                     10
       #                     11
       A--D              12--15
       Flash                 16
    */
63 64 65 66 67

    switch (digit) {
        case '*':
            digit = 10;
            break;
68

69 70 71
        case '#':
            digit = 11;
            break;
72

73 74 75
        case 'A' ... 'D':
            digit = digit - 'A' + 12;
            break;
76

77 78 79
        case '0' ... '9':
            digit = digit - '0';
            break;
80

81 82 83 84
        default:
            ERROR("Unexpected DTMF %c", digit);
    }

85 86 87 88
    payload.event = digit;
    payload.ebit = false; // end of event bit
    payload.rbit = false; // reserved bit
    payload.duration = 1; // duration for this event
89
    payload.vol = 10;
90 91
}

92
AudioRtpRecord::AudioRtpRecord() :
93
    callId_("")
94 95
    , codecSampleRate_(0)
    , dtmfQueue_()
96
    , audioCodecs_()
97
    , audioCodecMutex_()
98 99
    , encoderPayloadType_(0)
    , decoderPayloadType_(0)
100
    , hasDynamicPayloadType_(false)
101
    , decData_(DEC_BUFFER_SIZE)     // std::tr1::arrays will be 0-initialized
102
    , resampledData_(0)
103
    , encodedData_()
104 105
    , converterEncode_(0)
    , converterDecode_(0)
106
    , codecFrameSize_(0)
107
    , converterSamplingRate_(0)
108
    , fadeFactor_(1.0 / 32000.0)
109
#if HAVE_SPEEXDSP
110
    , noiseSuppressEncode_(0)
111
    , noiseSuppressDecode_(0)
112
    , audioProcessMutex_()
113
#endif
114
    , dtmfPayloadType_(101) // same as Asterisk
115
    , dead_(false)
116
    , currentCodecIndex_(0)
117
{}
118

119 120 121 122 123 124 125 126 127 128
// Call from processData*
bool AudioRtpRecord::isDead()
{
#ifdef CCPP_PREFIX
    return (int) dead_;
#else
    return *dead_;
#endif
}

129 130 131 132 133 134 135
sfl::AudioCodec *
AudioRtpRecord::getCurrentCodec() const
{
    if (audioCodecs_.empty() or currentCodecIndex_ >= audioCodecs_.size()) {
        ERROR("No codec found");
        return 0;
    }
136

137 138 139
    return audioCodecs_[currentCodecIndex_];
}

140 141 142
void
AudioRtpRecord::deleteCodecs()
{
143 144
    for (auto &i : audioCodecs_)
        delete i;
145

146 147 148
    audioCodecs_.clear();
}

149 150 151 152
bool AudioRtpRecord::tryToSwitchPayloadTypes(int newPt)
{
    for (std::vector<AudioCodec *>::iterator i = audioCodecs_.begin(); i != audioCodecs_.end(); ++i)
        if (*i and (*i)->getPayloadType() == newPt) {
153
            decoderPayloadType_ = (*i)->getPayloadType();
154 155 156 157 158 159 160 161 162 163 164 165
            codecSampleRate_ = (*i)->getClockRate();
            codecFrameSize_ = (*i)->getFrameSize();
            hasDynamicPayloadType_ = (*i)->hasDynamicPayload();
            currentCodecIndex_ = std::distance(audioCodecs_.begin(), i);
            DEBUG("Switched payload type to %d", newPt);
            return true;
        }

    ERROR("Could not switch payload types");
    return false;
}

166 167
AudioRtpRecord::~AudioRtpRecord()
{
168
    dead_ = true;
169
#ifdef RTP_DECODE_RECTODISK
170 171
    beforedecode.close();
    afterdecode.close();
172 173 174
#endif

    delete converterEncode_;
175
    converterEncode_ = 0;
176
    delete converterDecode_;
177
    converterDecode_ = 0;
178
    {
179
        std::lock_guard<std::mutex> lock(audioCodecMutex_);
180
        deleteCodecs();
181
    }
182
#if HAVE_SPEEXDSP
183
    {
184
        std::lock_guard<std::mutex> lock(audioProcessMutex_);
185
        delete noiseSuppressDecode_;
186
        noiseSuppressDecode_ = 0;
187
        delete noiseSuppressEncode_;
188
        noiseSuppressEncode_ = 0;
189
    }
190
#endif
191 192
}

193 194 195
AudioRtpRecordHandler::AudioRtpRecordHandler(SIPCall &call) :
    audioRtpRecord_(),
    id_(call.getCallId()),
Tristan Matthews's avatar
Tristan Matthews committed
196
    gainController_(8000, -10.0),
197
    warningInterval_(0)
198
{}
199 200


201
AudioRtpRecordHandler::~AudioRtpRecordHandler()
202 203
{
}
204

205 206 207 208
std::string
AudioRtpRecordHandler::getCurrentAudioCodecNames()
{
    std::string result;
209
    std::lock_guard<std::mutex> lock(audioRtpRecord_.audioCodecMutex_);
210 211
    {
        std::string sep = "";
212

213 214 215
        for (auto &i : audioRtpRecord_.audioCodecs_) {
            if (i)
                result += sep + i->getMimeSubtype();
216

217 218 219 220 221 222 223
            sep = " ";
        }
    }

    return result;
}

224
void AudioRtpRecordHandler::setRtpMedia(const std::vector<AudioCodec*> &audioCodecs)
Alexandre Savard's avatar
Alexandre Savard committed
225
{
226
    std::lock_guard<std::mutex> lock(audioRtpRecord_.audioCodecMutex_);
227

228
    audioRtpRecord_.deleteCodecs();
229
    // Set various codec info to reduce indirection
230
    audioRtpRecord_.audioCodecs_ = audioCodecs;
231

232 233 234 235
    if (audioCodecs.empty()) {
        ERROR("Audio codecs empty");
        return;
    }
236 237

    audioRtpRecord_.currentCodecIndex_ = 0;
238
    audioRtpRecord_.encoderPayloadType_ = audioRtpRecord_.decoderPayloadType_ = audioCodecs[0]->getPayloadType();
239 240 241
    audioRtpRecord_.codecSampleRate_ = audioCodecs[0]->getClockRate();
    audioRtpRecord_.codecFrameSize_ = audioCodecs[0]->getFrameSize();
    audioRtpRecord_.hasDynamicPayloadType_ = audioCodecs[0]->hasDynamicPayload();
242 243
}

244
void AudioRtpRecordHandler::initBuffers()
245 246
{
    // Set sampling rate, main buffer choose the highest one
247
    Manager::instance().audioSamplingRateChanged(audioRtpRecord_.codecSampleRate_);
248 249 250

    // initialize SampleRate converter using AudioLayer's sampling rate
    // (internal buffers initialized with maximal sampling rate and frame size)
251 252 253 254
    delete audioRtpRecord_.converterEncode_;
    audioRtpRecord_.converterEncode_ = new SamplerateConverter(getCodecSampleRate());
    delete audioRtpRecord_.converterDecode_;
    audioRtpRecord_.converterDecode_ = new SamplerateConverter(getCodecSampleRate());
255 256
}

257
#if HAVE_SPEEXDSP
258 259
void AudioRtpRecordHandler::initNoiseSuppress()
{
260
    std::lock_guard<std::mutex> lock(audioRtpRecord_.audioProcessMutex_);
261 262
    delete audioRtpRecord_.noiseSuppressEncode_;
    audioRtpRecord_.noiseSuppressEncode_ = new NoiseSuppress(getCodecFrameSize(), getCodecSampleRate());
263 264
    delete audioRtpRecord_.noiseSuppressDecode_;
    audioRtpRecord_.noiseSuppressDecode_ = new NoiseSuppress(getCodecFrameSize(), getCodecSampleRate());
265
}
266
#endif
267

268
void AudioRtpRecordHandler::putDtmfEvent(char digit)
269
{
270 271
    DTMFEvent dtmf(digit);
    audioRtpRecord_.dtmfQueue_.push_back(dtmf);
272 273
}

274 275
#define RETURN_IF_NULL(A, VAL, M, ...) if (!(A)) { ERROR(M, ##__VA_ARGS__); return VAL; }

276
int AudioRtpRecordHandler::processDataEncode()
277
{
278 279 280
    if (audioRtpRecord_.isDead())
        return 0;

281
    int codecSampleRate = getCodecSampleRate();
282
    int mainBufferSampleRate = Manager::instance().getMainBuffer().getInternalSamplingRate();
asavard's avatar
asavard committed
283

284
    double resampleFactor = (double) mainBufferSampleRate / codecSampleRate;
asavard's avatar
asavard committed
285

286 287 288
    // compute nb of byte to get corresponding to 1 audio frame
    const size_t samplesToGet = resampleFactor * getCodecFrameSize();

289 290
    if (Manager::instance().getMainBuffer().availableForGet(id_) < samplesToGet)
        return 0;
291

292 293
    AudioBuffer& micData = audioRtpRecord_.decData_;
    micData.resize(samplesToGet);
294
    const size_t samps = Manager::instance().getMainBuffer().getData(micData, id_);
295

296
#ifdef RECTODISK
297
    rtpNotResampled << micData;
298 299
#endif

300 301
    if (samps != samplesToGet) {
        ERROR("Asked for %d samples from mainbuffer, got %d", samplesToGet, samps);
Rafaël Carré's avatar
Rafaël Carré committed
302
        return 0;
303
    }
304

305
    audioRtpRecord_.fadeInDecodedData();
306

307
    AudioBuffer *out = &micData;
308

309
    if (codecSampleRate != mainBufferSampleRate) {
310
        RETURN_IF_NULL(audioRtpRecord_.converterEncode_, 0, "Converter already destroyed");
311

312
        micData.setSampleRate(mainBufferSampleRate);
313
        audioRtpRecord_.resampledData_.setSampleRate(codecSampleRate);
314
        audioRtpRecord_.converterEncode_->resample(micData, audioRtpRecord_.resampledData_);
315 316

#ifdef RECTODISK
317
        rtpResampled << audioRtpRecord_.resampledData_;
318 319
#endif

320
        out = &(audioRtpRecord_.resampledData_);
321
    }
322

323
#if HAVE_SPEEXDSP
324

325
    if (Manager::instance().audioPreference.getNoiseReduce()) {
326
        std::lock_guard<std::mutex> lock(audioRtpRecord_.audioProcessMutex_);
327
        RETURN_IF_NULL(audioRtpRecord_.noiseSuppressEncode_, 0, "Noise suppressor already destroyed");
328
        audioRtpRecord_.noiseSuppressEncode_->process(micData, getCodecFrameSize());
329
    }
330

331
#endif
332

333
#ifdef RTP_ENCODE_RECTODISK
334
    beforesend.write((const char *)(micData), getCodecFrameSize() * 2);
335 336
#endif

337
    {
338
        std::lock_guard<std::mutex> lock(audioRtpRecord_.audioCodecMutex_);
339
        RETURN_IF_NULL(audioRtpRecord_.getCurrentCodec(), 0, "Audio codec already destroyed");
340
        unsigned char *micDataEncoded = audioRtpRecord_.encodedData_.data();
341
        return audioRtpRecord_.getCurrentCodec()->encode(micDataEncoded, out->getData(), getCodecFrameSize());
342
    }
343
}
344 345 346
#undef RETURN_IF_NULL

#define RETURN_IF_NULL(A, M, ...) if (!(A)) { ERROR(M, ##__VA_ARGS__); return; }
347

Tristan Matthews's avatar
Tristan Matthews committed
348
void AudioRtpRecordHandler::processDataDecode(unsigned char *spkrData, size_t size, int payloadType)
349
{
350 351
    if (audioRtpRecord_.isDead())
        return;
352

353
    if (audioRtpRecord_.decoderPayloadType_ != payloadType) {
354
        const bool switched = audioRtpRecord_.tryToSwitchPayloadTypes(payloadType);
355

356 357 358
        if (not switched) {
            if (!warningInterval_) {
                warningInterval_ = 250;
359
                WARN("Invalid payload type %d, expected %d", payloadType, audioRtpRecord_.decoderPayloadType_);
360
            }
361

362 363
            warningInterval_--;
            return;
364 365
        }
    }
366

367
    size = std::min(size, audioRtpRecord_.decData_.frames());
368

369
    {
370
        std::lock_guard<std::mutex> lock(audioRtpRecord_.audioCodecMutex_);
371
        RETURN_IF_NULL(audioRtpRecord_.getCurrentCodec(), "Audio codecs already destroyed");
372
        // Return the size of data in samples
373
        audioRtpRecord_.getCurrentCodec()->decode(audioRtpRecord_.decData_.getData(), spkrData, size);
374
    }
375

376
#ifdef RTP_DECODE_RECTODISK
377
    afterdecode.write((const char *)spkrDataDecoded, inSamples * sizeof(SFLDataFormat));
378
#endif
379
#undef RTP_DECODE_RECTODISK
380

381
#if HAVE_SPEEXDSP
382

383
    if (Manager::instance().audioPreference.getNoiseReduce()) {
384
        std::lock_guard<std::mutex> lock(audioRtpRecord_.audioProcessMutex_);
385
        RETURN_IF_NULL(audioRtpRecord_.noiseSuppressDecode_, "Noise suppressor already destroyed");
386
        audioRtpRecord_.noiseSuppressDecode_->process(audioRtpRecord_.decData_, getCodecFrameSize());
387
    }
388

389
#endif
390

391
    audioRtpRecord_.fadeInDecodedData();
392

393
    // Normalize incoming signal
394
    gainController_.process(audioRtpRecord_.decData_);
395

396
    AudioBuffer *out = &(audioRtpRecord_.decData_);
397

398
    int codecSampleRate = out->getSampleRate();
399
    int mainBufferSampleRate = Manager::instance().getMainBuffer().getInternalSamplingRate();
400

Alexandre Savard's avatar
Alexandre Savard committed
401
    // test if resampling is required
402
    if (codecSampleRate != mainBufferSampleRate) {
403
        RETURN_IF_NULL(audioRtpRecord_.converterDecode_, "Converter already destroyed");
404
        out = &(audioRtpRecord_.resampledData_);
Alexandre Savard's avatar
Alexandre Savard committed
405
        // Do sample rate conversion
406
        audioRtpRecord_.converterDecode_->resample(audioRtpRecord_.decData_, audioRtpRecord_.resampledData_);
Alexandre Savard's avatar
Alexandre Savard committed
407
    }
408

409
    Manager::instance().getMainBuffer().putData(*out, id_);
410
}
411
#undef RETURN_IF_NULL
412

413
void AudioRtpRecord::fadeInDecodedData()
414
{
415
    // if factor reaches 1, this function should have no effect
416
    if (fadeFactor_ >= 1.0)
417
        return;
Alexandre Savard's avatar
Alexandre Savard committed
418

419
    decData_.applyGain(fadeFactor_);
420

421
    // Factor used to increase volume in fade in
422 423
    const double FADEIN_STEP_SIZE = 4.0;
    fadeFactor_ *= FADEIN_STEP_SIZE;
424
}
425 426 427 428 429

bool
AudioRtpRecordHandler::codecsDiffer(const std::vector<AudioCodec*> &codecs) const
{
    const std::vector<AudioCodec*> &current = audioRtpRecord_.audioCodecs_;
430

431 432
    if (codecs.size() != current.size())
        return true;
433

434 435 436
    for (const auto &i : codecs) {
        if (!i)
            continue;
437

438
        bool matched = false;
439

440 441 442 443 444 445
        for (const auto &j : current)
            if ((matched = i->getPayloadType() == j->getPayloadType()))
                break;

        if (not matched)
            return true;
446
    }
447

448 449 450
    return false;
}

451
}