Showing the changes to plugins/opusCodec/src/OpusEncoder.cpp (1 of 7 files). Show all
Unified · Split
| @@ -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 | |||