audio_rtp_record_handler.h 5.66 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
 *  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
16
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.
17 18 19 20 21 22 23 24 25 26 27 28 29
 *
 *  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.
 */

30 31
#ifndef AUDIO_RTP_RECORD_HANDLER_H__
#define AUDIO_RTP_RECORD_HANDLER_H__
32 33 34 35 36
#include <cstddef>

using std::ptrdiff_t;

#include <ccrtp/rtp.h>
37
#include <tr1/array>
38
#include <list>
39

40
class SIPCall;
41
#include "noncopyable.h"
42 43 44
#include "audio/codecs/audiocodec.h"
#include "audio/samplerateconverter.h"
#include "audio/noisesuppress.h"
45
#include "audio/gaincontrol.h"
46

47
namespace sfl {
48

49 50 51 52
// G.722 VoIP is typically carried in RTP payload type 9.[2] Note that IANA records the clock rate for type 9 G.722 as 8 kHz
// (instead of 16 kHz), RFC3551[3]  clarifies that this is due to a historical error and is retained in order to maintain backward
// compatibility. Consequently correct implementations represent the value 8,000 where required but encode and decode audio at 16 kHz.

53
inline uint32
54
timeval2microtimeout(const timeval& t)
Alexandre Savard's avatar
Alexandre Savard committed
55
{
56
    return ((t.tv_sec * 1000000ul) + t.tv_usec);
Alexandre Savard's avatar
Alexandre Savard committed
57
}
58

59
struct DTMFEvent {
60
    DTMFEvent(char digit);
61 62 63 64 65
    ost::RTPPacket::RFC2833Payload payload;
    bool newevent;
    int length;
};

66 67 68
/**
 * Class meant to store internal data in order to encode/decode,
 * resample, process, and packetize audio streams. This class should not be
69
 * handled directly. Use AudioRtpRecordHandler
70
 */
71
class AudioRtpRecord {
Alexandre Savard's avatar
Alexandre Savard committed
72
    public:
73
        AudioRtpRecord();
74
        ~AudioRtpRecord();
75 76 77
        std::string callId_;
        int codecSampleRate_;
        std::list<DTMFEvent> dtmfQueue_;
Alexandre Savard's avatar
Alexandre Savard committed
78

79
    private:
80 81 82 83
        AudioCodec *audioCodec_;
        ost::Mutex audioCodecMutex_;
        int codecPayloadType_;
        bool hasDynamicPayloadType_;
84
        std::tr1::array<SFLDataFormat, DEC_BUFFER_SIZE> decData_;
85 86
// FIXME: resampledData should be resized as needed
        std::tr1::array<SFLDataFormat, DEC_BUFFER_SIZE * 4> resampledData_;
87
        std::tr1::array<unsigned char, DEC_BUFFER_SIZE> encodedData_;
88 89
        SamplerateConverter *converterEncode_;
        SamplerateConverter *converterDecode_;
90 91
        int codecFrameSize_;
        int converterSamplingRate_;
92
        double fadeFactor_;
93 94

#if HAVE_SPEEXDSP
95
        NoiseSuppress *noiseSuppressEncode_;
96
        NoiseSuppress *noiseSuppressDecode_;
97
        ost::Mutex audioProcessMutex_;
98 99
#endif

100
        unsigned int dtmfPayloadType_;
101

102
        bool isDead();
103 104 105 106 107
        friend class AudioRtpRecordHandler;
        /**
        * Ramp In audio data to avoid audio click from peer
        */
        void fadeInDecodedData(size_t size);
108
        NON_COPYABLE(AudioRtpRecord);
109 110 111 112 113
#ifdef CCPP_PREFIX
        ost::AtomicCounter dead_;
#else
        ucommon::atomic::counter dead_;
#endif
114 115 116
};


117
class AudioRtpRecordHandler {
Alexandre Savard's avatar
Alexandre Savard committed
118
    public:
119
        AudioRtpRecordHandler(SIPCall &);
120
        virtual ~AudioRtpRecordHandler();
121

Alexandre Savard's avatar
Alexandre Savard committed
122 123 124
        /**
         *  Set rtp media for this session
         */
125
        void setRtpMedia(AudioCodec* audioCodec);
126

127 128
        AudioCodec *getAudioCodec() const {
            return audioRtpRecord_.audioCodec_;
Alexandre Savard's avatar
Alexandre Savard committed
129
        }
130

131 132
        int getCodecPayloadType() const {
            return audioRtpRecord_.codecPayloadType_;
Alexandre Savard's avatar
Alexandre Savard committed
133
        }
134

135 136
        int getCodecSampleRate() const {
            return audioRtpRecord_.codecSampleRate_;
Alexandre Savard's avatar
Alexandre Savard committed
137
        }
138

139 140
        int getCodecFrameSize() const {
            return audioRtpRecord_.codecFrameSize_;
Alexandre Savard's avatar
Alexandre Savard committed
141
        }
142

143 144
        bool getHasDynamicPayload() const {
            return audioRtpRecord_.hasDynamicPayloadType_;
Alexandre Savard's avatar
Alexandre Savard committed
145
        }
146

147
        bool hasDTMFPending() const {
148
            return not audioRtpRecord_.dtmfQueue_.empty();
Alexandre Savard's avatar
Alexandre Savard committed
149
        }
150

151
        const unsigned char *getMicDataEncoded() const {
152
            return audioRtpRecord_.encodedData_.data();
Alexandre Savard's avatar
Alexandre Savard committed
153
        }
154

155
        void initBuffers();
156

157
#if HAVE_SPEEXDSP
158
        void initNoiseSuppress();
159
#endif
160

Alexandre Savard's avatar
Alexandre Savard committed
161 162 163
        /**
         * Encode audio data from mainbuffer
         */
164
        int processDataEncode();
165

Alexandre Savard's avatar
Alexandre Savard committed
166 167 168
        /**
         * Decode audio data received from peer
         */
Tristan Matthews's avatar
Tristan Matthews committed
169
        void processDataDecode(unsigned char * spkrData, size_t size, int payloadType);
170

171
        void setDtmfPayloadType(unsigned int payloadType) {
172
            audioRtpRecord_.dtmfPayloadType_ = payloadType;
173 174
        }

175 176
        unsigned int getDtmfPayloadType() const {
            return audioRtpRecord_.dtmfPayloadType_;
177 178
        }

179
        void putDtmfEvent(char digit);
180

181
    protected:
Tristan Matthews's avatar
Tristan Matthews committed
182
        AudioRtpRecord audioRtpRecord_;
183

184
    private:
185
        const std::string id_;
186
        GainControl gainController;
187 188 189
};
}

190
#endif // AUDIO_RTP_RECORD_HANDLER_H__