~ubuntu-branches/ubuntu/wily/sflphone/wily

« back to all changes in this revision

Viewing changes to daemon/src/audio/codecs/opuscodec.cpp

  • Committer: Package Import Robot
  • Author(s): Francois Marier, Francois Marier, Mark Purcell
  • Date: 2014-10-18 15:08:50 UTC
  • mfrom: (1.1.12)
  • mto: This revision was merged to the branch mainline in revision 29.
  • Revision ID: package-import@ubuntu.com-20141018150850-2exfk34ckb15pcwi
Tags: 1.4.1-0.1
[ Francois Marier ]
* Non-maintainer upload
* New upstream release (closes: #759576, #741130)
  - debian/rules +PJPROJECT_VERSION := 2.2.1
  - add upstream patch to fix broken TLS support
  - add patch to fix pjproject regression

[ Mark Purcell ]
* Build-Depends:
  - sflphone-daemon + libavformat-dev, libavcodec-dev, libswscale-dev,
  libavdevice-dev, libavutil-dev
  - sflphone-gnome + libclutter-gtk-1.0-dev

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *  Copyright (C) 2004-2013 Savoir-Faire Linux Inc.
 
3
 *  Author:  Emmanuel Lepage <emmanuel.lepage@savoirfairelinux.com>
 
4
 *  Author: Adrien Beraud <adrien.beraud@wisdomvibes.com>
 
5
 *
 
6
 *  This program is free software; you can redistribute it and/or modify
 
7
 *  it under the terms of the GNU General Public License as published by
 
8
 *  the Free Software Foundation; either version 3 of the License, or
 
9
 *  (at your option) any later version.
 
10
 *
 
11
 *  This program is distributed in the hope that it will be useful,
 
12
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
 *  GNU General Public License for more details.
 
15
 *
 
16
 *  You should have received a copy of the GNU General Public License
 
17
 *  along with this program; if not, write to the Free Software
 
18
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.
 
19
 *
 
20
 *  Additional permission under GNU GPL version 3 section 7:
 
21
 *
 
22
 *  If you modify this program, or any covered work, by linking or
 
23
 *  combining it with the OpenSSL project's OpenSSL library (or a
 
24
 *  modified version of that library), containing parts covered by the
 
25
 *  terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc.
 
26
 *  grants you additional permission to convey the resulting work.
 
27
 *  Corresponding Source for a non-source form of such a combination
 
28
 *  shall include the source code for the parts of OpenSSL used as well
 
29
 *  as that of the covered work.
 
30
 */
 
31
#include "opuscodec.h"
 
32
#include "sfl_types.h"
 
33
#include <stdexcept>
 
34
#include <iostream>
 
35
#include <array>
 
36
 
 
37
constexpr uint32_t Opus::VALID_SAMPLING_RATE[];
 
38
 
 
39
Opus::Opus() : sfl::AudioCodec(PAYLOAD_TYPE, "opus", CLOCK_RATE, FRAME_SIZE, CHANNELS),
 
40
    encoder_(nullptr),
 
41
    decoder_(nullptr),
 
42
    lastDecodedFrameSize_(0)
 
43
{
 
44
    hasDynamicPayload_ = true;
 
45
    setOptimalFormat(CLOCK_RATE, 1);
 
46
}
 
47
 
 
48
Opus::~Opus()
 
49
{
 
50
    if (encoder_)
 
51
        opus_encoder_destroy(encoder_);
 
52
    if (decoder_)
 
53
        opus_decoder_destroy(decoder_);
 
54
}
 
55
 
 
56
sfl::AudioCodec *
 
57
Opus::clone()
 
58
{
 
59
    return new Opus;
 
60
}
 
61
 
 
62
void Opus::setOptimalFormat(uint32_t sample_rate, uint8_t channels)
 
63
{
 
64
    // Use a SR higher or equal to sample_rate.
 
65
    // Typical case: 44.1kHz => 48kHz.
 
66
    unsigned i = 0;
 
67
    while (i < VALID_SAMPLING_RATE_NUM - 1 and VALID_SAMPLING_RATE[i] < sample_rate)
 
68
        i++;
 
69
    sample_rate = VALID_SAMPLING_RATE[i];
 
70
 
 
71
    // Opus supports 1 or 2 channels.
 
72
    channels = std::max(std::min(channels, (uint8_t) 2), (uint8_t) 1);
 
73
 
 
74
    if (not (!encoder_ || !decoder_ || sample_rate != clockRateCur_ || channels != channelsCur_))
 
75
        return;
 
76
 
 
77
    clockRateCur_ = sample_rate;
 
78
    channelsCur_ = channels;
 
79
 
 
80
    int err;
 
81
    if (encoder_)
 
82
        opus_encoder_destroy(encoder_);
 
83
    encoder_ = opus_encoder_create(sample_rate, channels, OPUS_APPLICATION_VOIP, &err);
 
84
    if (err)
 
85
        throw std::runtime_error("opus: could not create encoder");
 
86
 
 
87
    if (decoder_)
 
88
        opus_decoder_destroy(decoder_);
 
89
    lastDecodedFrameSize_ = 0;
 
90
    decoder_ = opus_decoder_create(sample_rate, channels, &err);
 
91
    if (err)
 
92
        throw std::runtime_error("opus: could not create decoder");
 
93
}
 
94
 
 
95
// Reference: http://tools.ietf.org/html/draft-spittka-payload-rtp-opus-03#section-6.2
 
96
// "The RTP clock rate in "a=rtpmap" MUST be 48000..."
 
97
uint32_t Opus::getSDPClockRate() const
 
98
{
 
99
    return 48000;
 
100
}
 
101
 
 
102
// "...and the number of channels MUST be 2."
 
103
const char *
 
104
Opus::getSDPChannels() const
 
105
{
 
106
    return "2";
 
107
}
 
108
 
 
109
int Opus::decode(std::vector<std::vector<SFLAudioSample> > &pcm, const uint8_t *data, size_t len)
 
110
{
 
111
    if (data == nullptr) return 0;
 
112
 
 
113
    int ret;
 
114
    if (channelsCur_ == 1) {
 
115
        ret = opus_decode(decoder_, data, len, pcm[0].data(), MAX_PACKET_SIZE, 0);
 
116
    } else {
 
117
        std::array<SFLAudioSample, 2 * MAX_PACKET_SIZE> ibuf; // deinterleave on stack, 11.25KiB used.
 
118
        ret = opus_decode(decoder_, data, len, ibuf.data(), MAX_PACKET_SIZE, 0);
 
119
        for (int i = 0; i < ret; i++) {
 
120
            pcm[0][i] = ibuf[2 * i];
 
121
            pcm[1][i] = ibuf[2 * i + 1];
 
122
        }
 
123
    }
 
124
    if (ret < 0)
 
125
        std::cerr << opus_strerror(ret) << std::endl;
 
126
    lastDecodedFrameSize_ = ret;
 
127
    return ret;
 
128
}
 
129
 
 
130
int Opus::decode(std::vector<std::vector<SFLAudioSample> > &pcm)
 
131
{
 
132
    if (!lastDecodedFrameSize_) return 0;
 
133
    int ret;
 
134
    if (channelsCur_ == 1) {
 
135
        ret = opus_decode(decoder_, nullptr, 0, pcm[0].data(), lastDecodedFrameSize_, 0);
 
136
    } else {
 
137
        std::array<SFLAudioSample, 2 * MAX_PACKET_SIZE> ibuf; // deinterleave on stack, 11.25KiB used.
 
138
        ret = opus_decode(decoder_, nullptr, 0, ibuf.data(), lastDecodedFrameSize_, 0);
 
139
        for (int i = 0; i < ret; i++) {
 
140
            pcm[0][i] = ibuf[2 * i];
 
141
            pcm[1][i] = ibuf[2 * i + 1];
 
142
        }
 
143
    }
 
144
    if (ret < 0)
 
145
        std::cerr << opus_strerror(ret) << std::endl;
 
146
    return ret;
 
147
}
 
148
 
 
149
size_t Opus::encode(const std::vector<std::vector<SFLAudioSample> > &pcm, uint8_t *data, size_t len)
 
150
{
 
151
    if (data == nullptr) return 0;
 
152
    int ret;
 
153
    if (channelsCur_ == 1) {
 
154
        ret = opus_encode(encoder_, pcm[0].data(), FRAME_SIZE, data, len);
 
155
    } else {
 
156
        std::array<SFLAudioSample, 2 * FRAME_SIZE> ibuf; // interleave on stack, 1.875KiB used;
 
157
        for (unsigned i = 0; i < FRAME_SIZE; i++) {
 
158
            ibuf[2 * i] = pcm[0][i];
 
159
            ibuf[2 * i + 1] = pcm[1][i];
 
160
        }
 
161
        ret = opus_encode(encoder_, ibuf.data(), FRAME_SIZE, data, len);
 
162
    }
 
163
    if (ret < 0) {
 
164
        std::cerr << opus_strerror(ret) << std::endl;
 
165
        ret = 0;
 
166
    }
 
167
    return ret;
 
168
}
 
169
 
 
170
// cppcheck-suppress unusedFunction
 
171
extern "C" sfl::AudioCodec* AUDIO_CODEC_ENTRY()
 
172
{
 
173
    try {
 
174
        return new Opus;
 
175
    } catch (const std::runtime_error &e) {
 
176
        std::cerr << e.what() << std::endl;
 
177
        return 0;
 
178
    }
 
179
}
 
180
 
 
181
// cppcheck-suppress unusedFunction
 
182
extern "C" void destroy(sfl::AudioCodec* a)
 
183
{
 
184
    delete a;
 
185
}