Skip to content
Permalink
Browse files

Fix accidental CBR limit for large Opus frames.

With Opus frames are no longer limited to a duration of 10ms
like with CELT. This means a single frame can now become
bigger than previously possible. At our maximum supported rate
of 96kbit/s with 60ms frames a single frame will be 720 bytes.
Previously the encoding output buffer was 512 bytes which triggered
rate limiting in Opus to hit this goal.

This patch bumps the buffer size to 960 and uses boost::array instead
of a C-Style array to ensure future changes don't accidentally miss
places where the size of the buffer is relevant.
  • Loading branch information...
hacst committed Dec 29, 2013
1 parent 338f024 commit 5fa918be84cdcc218b7e2def33438f8ccbb9dd04
Showing with 23 additions and 11 deletions.
  1. +15 −8 src/mumble/AudioInput.cpp
  2. +8 −3 src/mumble/AudioInput.h
@@ -672,22 +672,22 @@ bool AudioInput::selectCodec() {
return true;
}

int AudioInput::encodeOpusFrame(short *source, int size, unsigned char *buffer) {
int AudioInput::encodeOpusFrame(short *source, int size, EncodingOutputBuffer& buffer) {
int len = 0;
#ifdef USE_OPUS
if (!bPreviousVoice)
opus_encoder_ctl(opusState, OPUS_RESET_STATE, NULL);

opus_encoder_ctl(opusState, OPUS_SET_BITRATE(iAudioQuality));

len = opus_encode(opusState, source, size, buffer, 512);
len = opus_encode(opusState, source, size, &buffer[0], buffer.size());
const int tenMsFrameCount = (size / iFrameSize);
iBitrate = (len * 100 * 8) / tenMsFrameCount;
#endif
return len;
}

int AudioInput::encodeCELTFrame(short *psSource, unsigned char *buffer) {
int AudioInput::encodeCELTFrame(short *psSource, EncodingOutputBuffer& buffer) {
int len = 0;
if (!cCodec)
return len;
@@ -698,7 +698,7 @@ int AudioInput::encodeCELTFrame(short *psSource, unsigned char *buffer) {
cCodec->celt_encoder_ctl(ceEncoder, CELT_SET_PREDICTION(0));

cCodec->celt_encoder_ctl(ceEncoder, CELT_SET_VBR_RATE(iAudioQuality));
len = cCodec->encode(ceEncoder, psSource, buffer, qMin(iAudioQuality / (8 * 100), 127));
len = cCodec->encode(ceEncoder, psSource, &buffer[0], qMin<int>(iAudioQuality / (8 * 100), buffer.size()));
iBitrate = len * 100 * 8;

return len;
@@ -843,7 +843,9 @@ void AudioInput::encodeAudioFrame() {

tIdle.restart();

unsigned char buffer[512];
EncodingOutputBuffer buffer;
Q_ASSERT(buffer.size() >= static_cast<size_t>(iAudioQuality / 100 * iAudioFrames / 8));

int len;

bool encoded = true;
@@ -852,8 +854,11 @@ void AudioInput::encodeAudioFrame() {

if (umtType == MessageHandler::UDPVoiceCELTAlpha || umtType == MessageHandler::UDPVoiceCELTBeta) {
len = encodeCELTFrame(psSource, buffer);
if (len == 0)
if (len <= 0) {
iBitrate = 0;
qWarning() << "encodeCELTFrame failed" << iBufferedFrames << iFrameSize << len;
return;
}
++iBufferedFrames;
} else if (umtType == MessageHandler::UDPVoiceOpus) {
encoded = false;
@@ -879,8 +884,10 @@ void AudioInput::encodeAudioFrame() {
}
}

if (encoded)
flushCheck(QByteArray(reinterpret_cast<const char *>(buffer), len), ! bIsSpeech);
if (encoded) {
flushCheck(QByteArray::fromRawData(
reinterpret_cast<char*>(&buffer[0]), len), !bIsSpeech);
}

if (! bIsSpeech)
iBitrate = 0;
@@ -32,6 +32,7 @@
#define MUMBLE_MUMBLE_AUDIOINPUT_H_

#include <boost/shared_ptr.hpp>
#include <boost/array.hpp>
#include <speex/speex.h>
#include <speex/speex_echo.h>
#include <speex/speex_preprocess.h>
@@ -98,9 +99,11 @@ class AudioInput : public QThread {

OpusEncoder *opusState;
bool selectCodec();
int encodeOpusFrame(short *source, int size, unsigned char *buffer);
int encodeSpeexFrame(short *pSource, unsigned char *buffer);
int encodeCELTFrame(short *pSource, unsigned char *buffer);

typedef boost::array<unsigned char, 960> EncodingOutputBuffer;

int encodeOpusFrame(short *source, int size, EncodingOutputBuffer& buffer);
int encodeCELTFrame(short *pSource, EncodingOutputBuffer& buffer);
protected:
MessageHandler::UDPMessageType umtType;
SampleFormat eMicFormat, eEchoFormat;
@@ -122,7 +125,9 @@ class AudioInput : public QThread {
CELTCodec *cCodec;
CELTEncoder *ceEncoder;

/// Encoded audio rate in bit/s
int iAudioQuality;
/// Number of 10ms audio "frames" per packet (!= frames in packet)
int iAudioFrames;

short *psMic;

0 comments on commit 5fa918b

Please sign in to comment.
You can’t perform that action at this time.