1 // Copyright 2005-2019 The Mumble Developers. All rights reserved.
2 // Use of this source code is governed by a BSD-style license
3 // that can be found in the LICENSE file at the root of the
4 // Mumble source tree or at <https://www.mumble.info/LICENSE>.
5
6 #include "mumble_pch.hpp"
7
8 #include "CELTCodec.h"
9
10 #include "Audio.h"
11 #include "Version.h"
12 #include "MumbleApplication.h"
13
14 #ifdef Q_CC_GNU
15 #define RESOLVE(var) { var = reinterpret_cast<__typeof__(var)>(qlCELT.resolve(#var)); bValid = bValid && (var != NULL); }
16 #else
17 #define RESOLVE(var) { * reinterpret_cast<void **>(&var) = static_cast<void *>(qlCELT.resolve(#var)); bValid = bValid && (var != NULL); }
18 #endif
19
20 #ifdef Q_OS_WIN
21 extern "C" {
22 void __cpuid(int a[4], int b);
23 };
24 #endif
25
CELTCodec(const QString & celt_version)26 CELTCodec::CELTCodec(const QString &celt_version) {
27 bValid = false;
28 cmMode = NULL;
29 qsVersion = celt_version;
30 iBitstreamVersion = INT_MIN;
31 qlCELT.setLoadHints(QLibrary::ResolveAllSymbolsHint);
32
33 QStringList alternatives;
34 #if defined(Q_OS_MAC)
35 alternatives << QString::fromLatin1("libcelt0.%1.dylib").arg(celt_version);
36 alternatives << QString::fromLatin1("celt0.%1.dylib").arg(celt_version);
37 alternatives << QString::fromLatin1("libcelt.%1.dylib").arg(celt_version);
38 alternatives << QString::fromLatin1("celt.%1.dylib").arg(celt_version);
39 #elif defined(Q_OS_UNIX)
40 alternatives << QString::fromLatin1("libcelt0.so.%1").arg(celt_version);
41 alternatives << QString::fromLatin1("libcelt.so.%1").arg(celt_version);
42 alternatives << QString::fromLatin1("celt.so.%1").arg(celt_version);
43 alternatives << QString::fromLatin1("libcelt-mumble.so.%1").arg(celt_version);
44 #else
45 int cpuinfo[4];
46 __cpuid(cpuinfo, 1);
47 if (cpuinfo[3] & 0x02000000) {
48 if (cpuinfo[3] & 0x04000000) {
49 if (cpuinfo[2] & 0x00000001) {
50 alternatives << QString::fromLatin1("celt0.%1.sse3.dll").arg(celt_version);
51 }
52 alternatives << QString::fromLatin1("celt0.%1.sse2.dll").arg(celt_version);
53 }
54 alternatives << QString::fromLatin1("celt0.%1.sse.dll").arg(celt_version);
55 }
56
57 alternatives << QString::fromLatin1("celt0.%1.dll").arg(celt_version);
58 #endif
59 foreach(const QString &lib, alternatives) {
60 qlCELT.setFileName(MumbleApplication::instance()->applicationVersionRootPath() + QLatin1String("/") + lib);
61 if (qlCELT.load()) {
62 bValid = true;
63 break;
64 }
65
66 #ifdef Q_OS_MAC
67 qlCELT.setFileName(QApplication::instance()->applicationDirPath() + QLatin1String("/../Codecs/") + lib);
68 if (qlCELT.load()) {
69 bValid = true;
70 break;
71 }
72 #endif
73
74 #ifdef PLUGIN_PATH
75 qlCELT.setFileName(QLatin1String(MUMTEXT(PLUGIN_PATH) "/") + lib);
76 if (qlCELT.load()) {
77 bValid = true;
78 break;
79 }
80 #endif
81
82 qlCELT.setFileName(lib);
83 if (qlCELT.load()) {
84 bValid = true;
85 break;
86 }
87 }
88
89 RESOLVE(celt_mode_destroy);
90 RESOLVE(celt_mode_info);
91
92 RESOLVE(celt_encoder_destroy);
93 RESOLVE(celt_encoder_ctl);
94
95 RESOLVE(celt_decoder_destroy);
96 RESOLVE(celt_decoder_ctl);
97 }
98
~CELTCodec()99 CELTCodec::~CELTCodec() {
100 if (cmMode)
101 celt_mode_destroy(const_cast<CELTMode *>(cmMode));
102 }
103
isValid() const104 bool CELTCodec::isValid() const {
105 return bValid;
106 }
107
bitstreamVersion() const108 int CELTCodec::bitstreamVersion() const {
109 if (cmMode && iBitstreamVersion == INT_MIN)
110 celt_mode_info(cmMode, CELT_GET_BITSTREAM_VERSION, reinterpret_cast<celt_int32 *>(&iBitstreamVersion));
111
112 return iBitstreamVersion;
113 }
114
version() const115 QString CELTCodec::version() const {
116 return qsVersion;
117 }
118
report() const119 void CELTCodec::report() const {
120 qWarning("CELT bitstream %08x from %s", bitstreamVersion(), qPrintable(qlCELT.fileName()));
121 }
122
CELTCodec070(const QString & celt_version)123 CELTCodec070::CELTCodec070(const QString &celt_version) : CELTCodec(celt_version) {
124 RESOLVE(celt_mode_create);
125 RESOLVE(celt_encoder_create);
126 RESOLVE(celt_decoder_create);
127 RESOLVE(celt_encode_float);
128 RESOLVE(celt_encode);
129 RESOLVE(celt_decode_float);
130 RESOLVE(celt_decode);
131 RESOLVE(celt_strerror);
132
133 if (bValid) {
134 cmMode = celt_mode_create(SAMPLE_RATE, SAMPLE_RATE / 100, NULL);
135 }
136 }
137
encoderCreate()138 CELTEncoder *CELTCodec070::encoderCreate() {
139 return celt_encoder_create(cmMode, 1, NULL);
140 }
141
decoderCreate()142 CELTDecoder *CELTCodec070::decoderCreate() {
143 return celt_decoder_create(cmMode, 1, NULL);
144 }
145
encode(CELTEncoder * st,const celt_int16 * pcm,unsigned char * compressed,int nbCompressedBytes)146 int CELTCodec070::encode(CELTEncoder *st, const celt_int16 *pcm, unsigned char *compressed, int nbCompressedBytes) {
147 return celt_encode(st, pcm, NULL, compressed, nbCompressedBytes);
148 }
149
decode_float(CELTDecoder * st,const unsigned char * data,int len,float * pcm)150 int CELTCodec070::decode_float(CELTDecoder *st, const unsigned char *data, int len, float *pcm) {
151 return celt_decode_float(st, data, len, pcm);
152 }
153
CELTCodec011(const QString & celt_version)154 CELTCodec011::CELTCodec011(const QString &celt_version) : CELTCodec(celt_version) {
155 RESOLVE(celt_mode_create);
156 RESOLVE(celt_encoder_create_custom);
157 RESOLVE(celt_decoder_create_custom);
158 RESOLVE(celt_encode_float);
159 RESOLVE(celt_encode);
160 RESOLVE(celt_decode_float);
161 RESOLVE(celt_decode);
162 RESOLVE(celt_strerror);
163
164 if (bValid) {
165 cmMode = celt_mode_create(SAMPLE_RATE, SAMPLE_RATE / 100, NULL);
166 }
167 }
168
encoderCreate()169 CELTEncoder *CELTCodec011::encoderCreate() {
170 return celt_encoder_create_custom(cmMode, 1, NULL);
171 }
172
decoderCreate()173 CELTDecoder *CELTCodec011::decoderCreate() {
174 return celt_decoder_create_custom(cmMode, 1, NULL);
175 }
176
encode(CELTEncoder * st,const celt_int16 * pcm,unsigned char * compressed,int nbCompressedBytes)177 int CELTCodec011::encode(CELTEncoder *st, const celt_int16 *pcm, unsigned char *compressed, int nbCompressedBytes) {
178 return celt_encode(st, pcm, SAMPLE_RATE / 100, compressed, nbCompressedBytes);
179 }
180
decode_float(CELTDecoder * st,const unsigned char * data,int len,float * pcm)181 int CELTCodec011::decode_float(CELTDecoder *st, const unsigned char *data, int len, float *pcm) {
182 return celt_decode_float(st, data, len, pcm, SAMPLE_RATE / 100);
183 }
184