History

Initial attempt at Opus compression.

Dale Glass committed 6 years ago

Commit cf56bf41 parent a39ad977 files · +486 −33Browse files

Showing the changes to plugins/opusCodec/src/OpusEncoder.cpp (1 of 7 files). Show all

Unified · Split

plugins/opusCodec/src/OpusEncoder.cpp+270−0
@@ -0,0 +1,270 @@
1
2#include <PerfStat.h>
3#include <QtCore/QLoggingCategory>
4
5#include "OpusEncoder.h"
6#include "OpusWrapper.h"
7#include "opus/opus.h"
8
9static QLoggingCategory encoder("AthenaOpusEncoder");
10
11static QString error_to_string(int error) {
12 switch (error) {
13 case OPUS_OK:
14 return "OK";
15 case OPUS_BAD_ARG:
16 return "One or more invalid/out of range arguments.";
17 case OPUS_BUFFER_TOO_SMALL:
18 return "The mode struct passed is invalid.";
19 case OPUS_INTERNAL_ERROR:
20 return "An internal error was detected.";
21 case OPUS_INVALID_PACKET:
22 return "The compressed data passed is corrupted.";
23 case OPUS_UNIMPLEMENTED:
24 return "Invalid/unsupported request number.";
25 case OPUS_INVALID_STATE:
26 return "An encoder or decoder structure is invalid or already freed.";
27 default:
28 return QString("Unknown error code: %i").arg(error);
29 }
30}
31
32
33
34AthenaOpusEncoder::AthenaOpusEncoder(int sampleRate, int numChannels)
35{
36 _opus_sample_rate = sampleRate;
37 _opus_channels = numChannels;
38
39 int error;
40
41 _encoder = opus_encoder_create(sampleRate, numChannels, DEFAULT_APPLICATION, &error);
42
43 if ( error != OPUS_OK ) {
44 qCCritical(encoder) << "Failed to initialize Opus encoder: " << error_to_string(error);
45 _encoder = nullptr;
46 return;
47 }
48
49 setBitrate(DEFAULT_BITRATE);
50 setComplexity(DEFAULT_COMPLEXITY);
51 setApplication(DEFAULT_APPLICATION);
52 setSignal(DEFAULT_SIGNAL);
53
54 qCDebug(encoder) << "Opus encoder initialized";
55}
56
57AthenaOpusEncoder::~AthenaOpusEncoder()
58{
59 opus_encoder_destroy(_encoder);
60}
61
62
63
64void AthenaOpusEncoder::encode(const QByteArray& decodedBuffer, QByteArray& encodedBuffer) {
65
66 PerformanceTimer perfTimer("AthenaOpusEncoder::encode");
67 assert(_encoder);
68
69 encodedBuffer.resize( decodedBuffer.size() );
70 int frame_size = decodedBuffer.length()/ _opus_channels / static_cast<int>(sizeof(opus_int16));
71
72 int bytes = opus_encode(_encoder, reinterpret_cast<const opus_int16*>(decodedBuffer.data()), frame_size, reinterpret_cast<unsigned char*>(encodedBuffer.data()), encodedBuffer.size() );
73
74 if ( bytes >= 0 ) {
75 qCDebug(encoder) << "Encoded " << decodedBuffer.length() << " bytes into " << bytes << " opus bytes";
76 encodedBuffer.resize(bytes);
77 } else {
78 encodedBuffer.resize(0);
79
80 qCWarning(encoder) << "Error when encoding " << decodedBuffer.length() << " bytes of audio: " << error_to_string(bytes);
81 }
82
83}
84
85int AthenaOpusEncoder::getComplexity() const
86{
87 assert(_encoder);
88 int ret;
89 opus_encoder_ctl(_encoder, OPUS_GET_COMPLEXITY(&ret));
90 return ret;
91}
92
93void AthenaOpusEncoder::setComplexity(int complexity)
94{
95 assert(_encoder);
96 int ret = opus_encoder_ctl(_encoder, OPUS_SET_COMPLEXITY(complexity));
97
98 if ( ret != OPUS_OK )
99 qCWarning(encoder) << "Error when setting complexity to " << complexity << ": " << error_to_string(ret);
100}
101
102int AthenaOpusEncoder::getBitrate() const
103{
104 assert(_encoder);
105 int ret;
106 opus_encoder_ctl(_encoder, OPUS_GET_BITRATE(&ret));
107 return ret;
108}
109
110void AthenaOpusEncoder::setBitrate(int bitrate)
111{
112 assert(_encoder);
113 int ret = opus_encoder_ctl(_encoder, OPUS_SET_BITRATE(bitrate));
114 if ( ret != OPUS_OK )
115 qCWarning(encoder) << "Error when setting bitrate to " << bitrate << ": " << error_to_string(ret);
116}
117
118int AthenaOpusEncoder::getVBR() const
119{
120 assert(_encoder);
121 int ret;
122 opus_encoder_ctl(_encoder, OPUS_GET_VBR(&ret));
123 return ret;
124}
125
126void AthenaOpusEncoder::setVBR(int vbr)
127{
128 assert(_encoder);
129 int ret = opus_encoder_ctl(_encoder, OPUS_SET_VBR(vbr));
130 if ( ret != OPUS_OK )
131 qCWarning(encoder) << "Error when setting VBR to " << vbr << ": " << error_to_string(ret);
132}
133
134int AthenaOpusEncoder::getVBRConstraint() const
135{
136 assert(_encoder);
137 int ret;
138 opus_encoder_ctl(_encoder, OPUS_GET_VBR_CONSTRAINT(&ret));
139 return ret;
140}
141
142void AthenaOpusEncoder::setVBRConstraint(int vbr_const)
143{
144 assert(_encoder);
145 int ret = opus_encoder_ctl(_encoder, OPUS_SET_VBR_CONSTRAINT(vbr_const));
146 if ( ret != OPUS_OK )
147 qCWarning(encoder) << "Error when setting VBR constraint to " << vbr_const << ": " << error_to_string(ret);
148}
149
150int AthenaOpusEncoder::getMaxBandwidth() const
151{
152 assert(_encoder);
153 int ret;
154 opus_encoder_ctl(_encoder, OPUS_GET_MAX_BANDWIDTH(&ret));
155 return ret;
156}
157
158void AthenaOpusEncoder::setMaxBandwidth(int maxbw)
159{
160 assert(_encoder);
161 int ret = opus_encoder_ctl(_encoder, OPUS_SET_MAX_BANDWIDTH(maxbw));
162 if ( ret != OPUS_OK )
163 qCWarning(encoder) << "Error when setting max bandwidth to " << maxbw << ": " << error_to_string(ret);
164}
165
166int AthenaOpusEncoder::getBandwidth() const
167{
168 assert(_encoder);
169 int ret;
170 opus_encoder_ctl(_encoder, OPUS_GET_BANDWIDTH(&ret));
171 return ret;
172}
173
174void AthenaOpusEncoder::setBandwidth(int bw)
175{
176 assert(_encoder);
177 int ret = opus_encoder_ctl(_encoder, OPUS_SET_BANDWIDTH(bw));
178 if ( ret != OPUS_OK )
179 qCWarning(encoder) << "Error when setting bandwidth to " << bw << ": " << error_to_string(ret);
180}
181
182int AthenaOpusEncoder::getSignal() const
183{
184 assert(_encoder);
185 int ret;
186 opus_encoder_ctl(_encoder, OPUS_GET_SIGNAL(&ret));
187 return ret;
188}
189
190void AthenaOpusEncoder::setSignal(int signal)
191{
192 assert(_encoder);
193 int ret = opus_encoder_ctl(_encoder, OPUS_SET_SIGNAL(signal));
194 if ( ret != OPUS_OK )
195 qCWarning(encoder) << "Error when setting signal to " << signal << ": " << error_to_string(ret);
196}
197
198int AthenaOpusEncoder::getApplication() const
199{
200 assert(_encoder);
201 int ret;
202 opus_encoder_ctl(_encoder, OPUS_GET_APPLICATION(&ret));
203 return ret;
204}
205
206void AthenaOpusEncoder::setApplication(int app)
207{
208 assert(_encoder);
209 int ret = opus_encoder_ctl(_encoder, OPUS_SET_APPLICATION(app));
210 if ( ret != OPUS_OK )
211 qCWarning(encoder) << "Error when setting application to " << app << ": " << error_to_string(ret);
212}
213
214int AthenaOpusEncoder::getLookahead() const
215{
216 assert(_encoder);
217 int ret;
218 opus_encoder_ctl(_encoder, OPUS_GET_LOOKAHEAD(&ret));
219 return ret;
220}
221
222int AthenaOpusEncoder::getInbandFEC() const
223{
224 assert(_encoder);
225 int ret;
226 opus_encoder_ctl(_encoder, OPUS_GET_INBAND_FEC(&ret));
227 return ret;
228}
229
230void AthenaOpusEncoder::setInbandFEC(int fec)
231{
232 assert(_encoder);
233 int ret = opus_encoder_ctl(_encoder, OPUS_SET_INBAND_FEC(fec));
234 if ( ret != OPUS_OK )
235 qCWarning(encoder) << "Error when setting inband FEC to " << fec << ": " << error_to_string(ret);
236}
237
238int AthenaOpusEncoder::getExpectedPacketLossPercent() const
239{
240 assert(_encoder);
241 int ret;
242 opus_encoder_ctl(_encoder, OPUS_GET_PACKET_LOSS_PERC(&ret));
243 return ret;
244}
245
246void AthenaOpusEncoder::setExpectedPacketLossPercent(int perc)
247{
248 assert(_encoder);
249 int ret = opus_encoder_ctl(_encoder, OPUS_SET_PACKET_LOSS_PERC(perc));
250 if ( ret != OPUS_OK )
251 qCWarning(encoder) << "Error when setting loss percent to " << perc << ": " << error_to_string(ret);
252}
253
254int AthenaOpusEncoder::getDTX() const
255{
256 assert(_encoder);
257 int ret;
258 opus_encoder_ctl(_encoder, OPUS_GET_DTX(&ret));
259 return ret;
260}
261
262void AthenaOpusEncoder::setDTX(int dtx)
263{
264 assert(_encoder);
265 int ret = opus_encoder_ctl(_encoder, OPUS_SET_DTX(dtx));
266 if ( ret != OPUS_OK )
267 qCWarning(encoder) << "Error when setting DTX to " << dtx << ": " << error_to_string(ret);
268}
269
270