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+
9+static QLoggingCategory encoder("AthenaOpusEncoder");
10+
11+static 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+
34+AthenaOpusEncoder::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+
57+AthenaOpusEncoder::~AthenaOpusEncoder()
58+{
59+ opus_encoder_destroy(_encoder);
60+}
61+
62+
63+
64+void 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+
85+int AthenaOpusEncoder::getComplexity() const
86+{
87+ assert(_encoder);
88+ int ret;
89+ opus_encoder_ctl(_encoder, OPUS_GET_COMPLEXITY(&ret));
90+ return ret;
91+}
92+
93+void 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+
102+int AthenaOpusEncoder::getBitrate() const
103+{
104+ assert(_encoder);
105+ int ret;
106+ opus_encoder_ctl(_encoder, OPUS_GET_BITRATE(&ret));
107+ return ret;
108+}
109+
110+void 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+
118+int AthenaOpusEncoder::getVBR() const
119+{
120+ assert(_encoder);
121+ int ret;
122+ opus_encoder_ctl(_encoder, OPUS_GET_VBR(&ret));
123+ return ret;
124+}
125+
126+void 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+
134+int 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+
142+void 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+
150+int 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+
158+void 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+
166+int AthenaOpusEncoder::getBandwidth() const
167+{
168+ assert(_encoder);
169+ int ret;
170+ opus_encoder_ctl(_encoder, OPUS_GET_BANDWIDTH(&ret));
171+ return ret;
172+}
173+
174+void 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+
182+int AthenaOpusEncoder::getSignal() const
183+{
184+ assert(_encoder);
185+ int ret;
186+ opus_encoder_ctl(_encoder, OPUS_GET_SIGNAL(&ret));
187+ return ret;
188+}
189+
190+void 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+
198+int AthenaOpusEncoder::getApplication() const
199+{
200+ assert(_encoder);
201+ int ret;
202+ opus_encoder_ctl(_encoder, OPUS_GET_APPLICATION(&ret));
203+ return ret;
204+}
205+
206+void 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+
214+int AthenaOpusEncoder::getLookahead() const
215+{
216+ assert(_encoder);
217+ int ret;
218+ opus_encoder_ctl(_encoder, OPUS_GET_LOOKAHEAD(&ret));
219+ return ret;
220+}
221+
222+int 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+
230+void 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+
238+int 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+
246+void 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+
254+int AthenaOpusEncoder::getDTX() const
255+{
256+ assert(_encoder);
257+ int ret;
258+ opus_encoder_ctl(_encoder, OPUS_GET_DTX(&ret));
259+ return ret;
260+}
261+
262+void 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+