audio_rtp_session.cpp 9.81 KB
Newer Older
1
/*
2
 *  Copyright (C) 2004-2012 Savoir-Faire Linux Inc.
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
 *  Author: Pierre-Luc Bacon <pierre-luc.bacon@savoirfairelinux.com>
 *  Author: Alexandre Bourget <alexandre.bourget@savoirfairelinux.com>
 *  Author: Laurielle Lea <laurielle.lea@savoirfairelinux.com>
 *  Author: Emmanuel Milou <emmanuel.milou@savoirfairelinux.com>
 *  Author: Yan Morin <yan.morin@savoirfairelinux.com>
 *  Author: Alexandre Savard <alexandre.savard@savoirfairelinux.com>
 *
 *  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
21
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.
22
23
24
25
26
27
28
29
30
31
32
33
34
 *
 *  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.
 */

35
#include "audio_rtp_session.h"
36
#include "logger.h"
37
#include "sip/sdp.h"
38
#include "sip/sipcall.h"
39
#include <ccrtp/oqueue.h>
40
#include "manager.h"
41

42
namespace sfl {
43
AudioRtpSession::AudioRtpSession(SIPCall &call, ost::RTPDataQueue &queue) :
44
    AudioRtpRecordHandler(call)
45
46
    , isStarted_(false)
    , queue_(queue)
47
    , call_(call)
48
49
    , timestamp_(0)
    , timestampIncrement_(0)
50
    , transportRate_(20)
51
52
53
    , remote_ip_()
    , remote_port_(0)
    , timestampCount_(0)
54
    , rtpSendThread_(*this)
55
{
56
    queue_.setTypeOfService(ost::RTPDataQueue::tosEnhanced);
57
58
59
60
}

AudioRtpSession::~AudioRtpSession()
{
61
    queue_.disableStack();
62
63
}

64
void AudioRtpSession::updateSessionMedia(const std::vector<AudioCodec*> &audioCodecs)
65
{
66
    int lastSamplingRate = audioRtpRecord_.codecSampleRate_;
67

68
69
    if (codecsDiffer(audioCodecs))
        setSessionMedia(audioCodecs);
70

71
    Manager::instance().audioSamplingRateChanged(audioRtpRecord_.codecSampleRate_);
72

73
#if HAVE_SPEEXDSP
74

75
    if (lastSamplingRate != audioRtpRecord_.codecSampleRate_) {
76
77
        DEBUG("Update noise suppressor with sampling rate %d and frame size %d",
              getCodecSampleRate(), getCodecFrameSize());
78
        initNoiseSuppress();
79
    }
80

81
#endif
82
83
}

84
void AudioRtpSession::setSessionMedia(const std::vector<AudioCodec*> &audioCodecs)
85
{
86
    setRtpMedia(audioCodecs);
87

88
    // G722 requires timestamp to be incremented at 8kHz
89
    const ost::PayloadType payloadType = getEncoderPayloadType();
90

91
92
93
94
95
96
97
98
    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;
99
        queue_.setPayloadFormat(ost::DynamicPayloadFormat(payloadType, G722_RTP_CLOCK_RATE));
100
    } else {
101
102
103
104
        if (getHasDynamicPayload())
            queue_.setPayloadFormat(ost::DynamicPayloadFormat(payloadType, getCodecSampleRate()));
        else
            queue_.setPayloadFormat(ost::StaticPayloadFormat(static_cast<ost::StaticPayloadType>(payloadType)));
105
    }
106
107
108
109
110
111

    call_.setRecordingSmplRate(getCodecSampleRate());

    int transportRate = getCodecFrameSize() / (getCodecSampleRate() / 1000);
    transportRate_ = (transportRate > 0)?transportRate:20;
    DEBUG("Switching to a transport rate of %d ms",transportRate_);
112
}
113

114
void AudioRtpSession::sendDtmfEvent()
115
{
116
117
    DTMFEvent &dtmf(audioRtpRecord_.dtmfQueue_.front());
    DEBUG("Send RTP Dtmf (%d)", dtmf.payload.event);
118

119
120
    const int increment = getIncrementForDTMF();
    timestamp_ += increment;
121
122
123
124
125

    // discard equivalent size of audio
    processDataEncode();

    // change Payload type for DTMF payload
126
    queue_.setPayloadFormat(ost::DynamicPayloadFormat((ost::PayloadType) getDtmfPayloadType(), 8000));
127

128
129
130
    // Set marker in case this is a new Event
    if (dtmf.newevent)
        queue_.setMark(true);
131

132
133
134
135
136
    // Send end packet three times (without changing it). Sequence number is
    // incremented automatically by ccrtp, which is the correct behaviour.
    const unsigned repetitions = dtmf.payload.ebit ? 3 : 1;
    for (unsigned i = 0; i < repetitions; ++i)
        queue_.sendImmediate(timestamp_, (const unsigned char *)(& (dtmf.payload)), sizeof(ost::RTPPacket::RFC2833Payload));
137

138
139
140
141
142
143
144
    // This is no longer a new event
    if (dtmf.newevent) {
        dtmf.newevent = false;
        queue_.setMark(false);
    }

    // restore the payload to audio
145
    const ost::StaticPayloadFormat pf(static_cast<ost::StaticPayloadType>(getEncoderPayloadType()));
146
    queue_.setPayloadFormat(pf);
147
148
149
150

    // decrease length remaining to process for this event
    dtmf.length -= increment;
    dtmf.payload.duration++;
151

152
    // next packet is going to be the end packet (transmitted 3 times)
153
154
    if ((dtmf.length - increment) < increment)
        dtmf.payload.ebit = true;
155

156
157
    if (dtmf.length < increment)
        audioRtpRecord_.dtmfQueue_.pop_front();
158
159
160
}


161
void AudioRtpSession::receiveSpeakerData()
162
{
163
    const ost::AppDataUnit* adu = queue_.getData(queue_.getFirstTimestamp());
164

165
    if (!adu)
166
167
        return;

168
    unsigned char* spkrDataIn = (unsigned char*) adu->getData(); // data in char
169
    size_t size = adu->getSize(); // size in char
170
171

    // DTMF over RTP, size must be over 4 in order to process it as voice data
172
    if (size > 4)
173
        processDataDecode(spkrDataIn, size, adu->getType());
174
175
176
177
178
179
180
181
182
183

    delete adu;
}


void AudioRtpSession::sendMicData()
{
    int compSize = processDataEncode();

    // if no data return
184
    if (compSize == 0)
185
186
187
        return;

    // Increment timestamp for outgoing packet
188
    timestamp_ += timestampIncrement_;
189

190
    // putData puts the data on RTP queue, sendImmediate bypass this queue
191
    queue_.sendImmediate(timestamp_, getMicDataEncoded(), compSize);
192
193
194
}


195
void AudioRtpSession::setSessionTimeouts()
196
{
197
198
    const int schedulingTimeout = 4000;
    const int expireTimeout = 1000000;
199
    DEBUG("Set session scheduling timeout (%d) and expireTimeout (%d)",
200
          schedulingTimeout, expireTimeout);
201

202
203
    queue_.setSchedulingTimeout(schedulingTimeout);
    queue_.setExpireTimeout(expireTimeout);
204
205
}

206
void AudioRtpSession::setDestinationIpAddress()
207
208
{
    // Store remote ip in case we would need to forget current destination
209
    remote_ip_ = ost::InetHostAddress(call_.getLocalSDP()->getRemoteIP().c_str());
210

211
    if (!remote_ip_) {
212
        WARN("Target IP address (%s) is not correct!",
213
             call_.getLocalSDP()->getRemoteIP().data());
214
215
216
217
        return;
    }

    // Store remote port in case we would need to forget current destination
218
    remote_port_ = (unsigned short) call_.getLocalSDP()->getRemoteAudioPort();
219

220
    DEBUG("New remote address for session: %s:%d",
221
          call_.getLocalSDP()->getRemoteIP().data(), remote_port_);
222

223
    if (!queue_.addDestination(remote_ip_, remote_port_)) {
224
        WARN("Can't add new destination to session!");
225
226
227
228
        return;
    }
}

229
void AudioRtpSession::updateDestinationIpAddress()
230
{
231
    DEBUG("Update destination ip address");
232
233
234
235

    // Destination address are stored in a list in ccrtp
    // This method remove the current destination entry

236
    if (!queue_.forgetDestination(remote_ip_, remote_port_))
237
        DEBUG("Did not remove previous destination");
238
239
240
241
242
243
244

    // new destination is stored in call
    // we just need to recall this method
    setDestinationIpAddress();
}


245
void AudioRtpSession::prepareRtpReceiveThread(const std::vector<AudioCodec*> &audioCodecs)
246
{
247
    DEBUG("Preparing receiving thread");
248
    isStarted_ = true;
249
    setSessionTimeouts();
250
    setSessionMedia(audioCodecs);
251
    initBuffers();
252
#if HAVE_SPEEXDSP
253
    initNoiseSuppress();
254
#endif
255

256
    queue_.enableStack();
257
258
259
}


260
bool AudioRtpSession::onRTPPacketRecv(ost::IncomingRTPPkt&)
261
262
263
264
265
{
    receiveSpeakerData();
    return true;
}

266
267
268
269
270
int AudioRtpSession::getIncrementForDTMF() const
{
    return timestampIncrement_;
}

271
272
273
274
275
276
277
278
279
280
281
void AudioRtpSession::startRtpThreads(const std::vector<AudioCodec*> &audioCodecs)
{
    if (isStarted_)
        return;

    prepareRtpReceiveThread(audioCodecs);
    // implemented in subclasses
    startReceiveThread();
    startSendThread();
}

282
283
284
285
286
287
288
AudioRtpSession::AudioRtpSendThread::AudioRtpSendThread(AudioRtpSession &session) :
    running_(false), rtpSession_(session), thread_(0), timer_()
{}

AudioRtpSession::AudioRtpSendThread::~AudioRtpSendThread()
{
    running_ = false;
289

290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
    if (thread_)
        pthread_join(thread_, NULL);
}

void AudioRtpSession::AudioRtpSendThread::start()
{
    running_ = true;
    pthread_create(&thread_, NULL, &runCallback, this);
}

void *
AudioRtpSession::AudioRtpSendThread::runCallback(void *data)
{
    AudioRtpSession::AudioRtpSendThread *context = static_cast<AudioRtpSession::AudioRtpSendThread*>(data);
    context->run();
    return NULL;
}

void AudioRtpSession::AudioRtpSendThread::run()
{
    timer_.setTimer(rtpSession_.transportRate_);
    const int MS_TO_USEC = 1000;

    while (running_) {
        // Send session
        if (rtpSession_.hasDTMFPending())
            rtpSession_.sendDtmfEvent();
        else
            rtpSession_.sendMicData();

        usleep(timer_.getTimer() * MS_TO_USEC);

        timer_.incTimer(rtpSession_.transportRate_);
    }
}


void AudioRtpSession::startSendThread()
{
    rtpSendThread_.start();
}
331
}