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/OpusDecoder.cpp (1 of 7 files). Show all

Unified · Split

plugins/opusCodec/src/OpusDecoder.cpp+97−0
@@ -0,0 +1,97 @@
1+#include <PerfStat.h>
2+#include <QtCore/QLoggingCategory>
3+
4+
5+
6+#include "OpusDecoder.h"
7+
8+static QLoggingCategory decoder("AthenaOpusDecoder");
9+
10+static QString error_to_string(int error) {
11+ switch (error) {
12+ case OPUS_OK:
13+ return "OK";
14+ case OPUS_BAD_ARG:
15+ return "One or more invalid/out of range arguments.";
16+ case OPUS_BUFFER_TOO_SMALL:
17+ return "The mode struct passed is invalid.";
18+ case OPUS_INTERNAL_ERROR:
19+ return "An internal error was detected.";
20+ case OPUS_INVALID_PACKET:
21+ return "The compressed data passed is corrupted.";
22+ case OPUS_UNIMPLEMENTED:
23+ return "Invalid/unsupported request number.";
24+ case OPUS_INVALID_STATE:
25+ return "An encoder or decoder structure is invalid or already freed.";
26+ default:
27+ return QString("Unknown error code: %i").arg(error);
28+ }
29+}
30+
31+
32+AthenaOpusDecoder::AthenaOpusDecoder(int sampleRate, int numChannels)
33+{
34+ int error;
35+
36+ _opus_sample_rate = sampleRate;
37+ _opus_num_channels = numChannels;
38+
39+ _decoder = opus_decoder_create(sampleRate, numChannels, &error);
40+
41+ if ( error != OPUS_OK ) {
42+ qCCritical(decoder) << "Failed to initialize Opus encoder: " << error_to_string(error);
43+ _decoder = nullptr;
44+ return;
45+ }
46+
47+
48+ qCDebug(decoder) << "Opus decoder initialized";
49+}
50+
51+AthenaOpusDecoder::~AthenaOpusDecoder()
52+{
53+ if ( _decoder )
54+ opus_decoder_destroy(_decoder);
55+
56+}
57+
58+void AthenaOpusDecoder::decode(const QByteArray &encodedBuffer, QByteArray &decodedBuffer)
59+{
60+ assert(_decoder);
61+
62+ PerformanceTimer perfTimer("AthenaOpusDecoder::decode");
63+
64+ decodedBuffer.resize( 65536 ); // Brute force, yeah!
65+ int frame_size = decodedBuffer.size() / _opus_num_channels / static_cast<int>(sizeof( opus_int16 ));
66+
67+ int frames = opus_decode( _decoder, reinterpret_cast<const unsigned char*>(encodedBuffer.data()), encodedBuffer.length(), reinterpret_cast<opus_int16*>(decodedBuffer.data()), frame_size, 1 );
68+
69+ if ( frames >= 0 ) {
70+ qCDebug(decoder) << "Decoded " << frames << " Opus frames";
71+ decodedBuffer.resize( frames * static_cast<int>(sizeof( opus_int16 )) * _opus_num_channels );
72+ } else {
73+ qCCritical(decoder) << "Failed to decode audio: " << error_to_string(frames);
74+ }
75+
76+}
77+
78+void AthenaOpusDecoder::lostFrame(QByteArray &decodedBuffer)
79+{
80+ assert(_decoder);
81+
82+ PerformanceTimer perfTimer("AthenaOpusDecoder::lostFrame");
83+
84+ decodedBuffer.resize( 65536 ); // Brute force, yeah!
85+ int frame_size = decodedBuffer.size() / _opus_num_channels / static_cast<int>(sizeof( opus_int16 ));
86+
87+ int frames = opus_decode( _decoder, nullptr, 0, reinterpret_cast<opus_int16*>(decodedBuffer.data()), frame_size, 1 );
88+
89+ if ( frames >= 0 ) {
90+ qCDebug(decoder) << "Produced " << frames << " opus frames from a lost frame";
91+ decodedBuffer.resize( frames * static_cast<int>(sizeof( opus_int16 )) * _opus_num_channels );
92+ } else {
93+ qCCritical(decoder) << "Failed to decode lost frame: " << error_to_string(frames);
94+ }
95+}
96+
97+