diff options
-rw-r--r-- | src/Message.h | 5 | ||||
-rw-r--r-- | src/Mumble.proto | 6 | ||||
-rw-r--r-- | src/mumble/AudioInput.cpp | 10 | ||||
-rw-r--r-- | src/mumble/AudioOutput.cpp | 8 | ||||
-rw-r--r-- | src/mumble/Messages.cpp | 3 | ||||
-rw-r--r-- | src/mumble/ServerHandler.cpp | 4 | ||||
-rw-r--r-- | src/murmur/Messages.cpp | 19 | ||||
-rw-r--r-- | src/murmur/Server.cpp | 58 | ||||
-rw-r--r-- | src/murmur/Server.h | 7 |
9 files changed, 104 insertions, 16 deletions
diff --git a/src/Message.h b/src/Message.h index 93d9effb3..13031eeaf 100644 --- a/src/Message.h +++ b/src/Message.h @@ -55,11 +55,12 @@ MUMBLE_MH_MSG(ContextAction) \ MUMBLE_MH_MSG(UserList) \ MUMBLE_MH_MSG(VoiceTarget) \ - MUMBLE_MH_MSG(PermissionQuery) + MUMBLE_MH_MSG(PermissionQuery) \ + MUMBLE_MH_MSG(CodecVersion) class MessageHandler { public: - enum UDPMessageType { UDPVoiceCELT, UDPPing, UDPVoiceSpeex }; + enum UDPMessageType { UDPVoiceCELTAlpha, UDPPing, UDPVoiceSpeex, UDPVoiceCELTBeta }; #define MUMBLE_MH_MSG(x) x, enum MessageType { diff --git a/src/Mumble.proto b/src/Mumble.proto index b876f9638..9523033c3 100644 --- a/src/Mumble.proto +++ b/src/Mumble.proto @@ -215,3 +215,9 @@ message PermissionQuery { optional uint32 permissions = 2; optional bool flush = 3 [default = false]; } + +message CodecVersion { + required int32 alpha = 1; + required int32 beta = 2; + required bool prefer_alpha = 3 [default = true]; +} diff --git a/src/mumble/AudioInput.cpp b/src/mumble/AudioInput.cpp index 5c6c66b13..202f03765 100644 --- a/src/mumble/AudioInput.cpp +++ b/src/mumble/AudioInput.cpp @@ -89,11 +89,11 @@ AudioInput::AudioInput() { g.iAudioBandwidth = getNetworkBandwidth(iAudioQuality, iAudioFrames); if (preferCELT(iAudioQuality, iAudioFrames)) - umtType = MessageHandler::UDPVoiceCELT; + umtType = MessageHandler::UDPVoiceCELTAlpha; else umtType = MessageHandler::UDPVoiceSpeex; - if (umtType == MessageHandler::UDPVoiceCELT) { + if (umtType == MessageHandler::UDPVoiceCELTAlpha) { iSampleRate = SAMPLE_RATE; iFrameSize = SAMPLE_RATE / 100; @@ -184,7 +184,7 @@ AudioInput::~AudioInput() { bRunning = false; wait(); - if (umtType == MessageHandler::UDPVoiceCELT) { + if (umtType == MessageHandler::UDPVoiceCELTAlpha) { cCodec->celt_encoder_destroy(ceEncoder); } else { speex_bits_destroy(&sbBits); @@ -522,7 +522,7 @@ void AudioInput::setMaxBandwidth(int bitspersec) { } AudioInputPtr ai = g.ai; - if (ai && (preferCELT(bitrate, frames) == (ai->umtType == MessageHandler::UDPVoiceCELT))) { + if (ai && (preferCELT(bitrate, frames) == (ai->umtType == MessageHandler::UDPVoiceCELTAlpha))) { g.iAudioBandwidth = getNetworkBandwidth(bitrate, frames); ai->iAudioQuality = bitrate; ai->iAudioFrames = frames; @@ -768,7 +768,7 @@ void AudioInput::encodeAudioFrame() { unsigned char buffer[512]; int len; - if (umtType == MessageHandler::UDPVoiceCELT) { + if (umtType == MessageHandler::UDPVoiceCELTAlpha) { cCodec->celt_encoder_ctl(ceEncoder,CELT_SET_VBR_RATE(iAudioQuality)); len = cCodec->celt_encode(ceEncoder, psSource, NULL, buffer, qMin(iAudioQuality / 800, 127)); diff --git a/src/mumble/AudioOutput.cpp b/src/mumble/AudioOutput.cpp index d0912428f..453162a7d 100644 --- a/src/mumble/AudioOutput.cpp +++ b/src/mumble/AudioOutput.cpp @@ -375,7 +375,7 @@ AudioOutputSpeech::AudioOutputSpeech(ClientUser *user, unsigned int freq, Messag unsigned int srate = 0; - if (umtType == MessageHandler::UDPVoiceCELT) { + if (umtType == MessageHandler::UDPVoiceCELTAlpha) { srate = SAMPLE_RATE; iFrameSize = srate / 100; cCodec = g.qmCodecs.value(0x8000000a); @@ -421,7 +421,7 @@ AudioOutputSpeech::AudioOutputSpeech(ClientUser *user, unsigned int freq, Messag } AudioOutputSpeech::~AudioOutputSpeech() { - if (umtType == MessageHandler::UDPVoiceCELT) { + if (umtType == MessageHandler::UDPVoiceCELTAlpha) { cCodec->celt_decoder_destroy(cdDecoder); } else { speex_bits_destroy(&sbBits); @@ -556,7 +556,7 @@ bool AudioOutputSpeech::needSamples(unsigned int snum) { if (! qlFrames.isEmpty()) { QByteArray qba = qlFrames.takeFirst(); - if (umtType == MessageHandler::UDPVoiceCELT) + if (umtType == MessageHandler::UDPVoiceCELTAlpha) cCodec->celt_decode_float(cdDecoder, reinterpret_cast<const unsigned char *>(qba.constData()), qba.size(), pOut); else { speex_bits_read_from(&sbBits, qba.data(), qba.size()); @@ -594,7 +594,7 @@ bool AudioOutputSpeech::needSamples(unsigned int snum) { if (qlFrames.isEmpty() && bHasTerminator) nextalive = false; } else { - if (umtType == MessageHandler::UDPVoiceCELT) + if (umtType == MessageHandler::UDPVoiceCELTAlpha) cCodec->celt_decode_float(cdDecoder, NULL, 0, pOut); else { speex_decode(dsSpeex, NULL, pOut); diff --git a/src/mumble/Messages.cpp b/src/mumble/Messages.cpp index 702b006b5..c16907df0 100644 --- a/src/mumble/Messages.cpp +++ b/src/mumble/Messages.cpp @@ -538,3 +538,6 @@ void MainWindow::msgPermissionQuery(const MumbleProto::PermissionQuery &msg) { } } } + +void MainWindow::msgCodecVersion(const MumbleProto::CodecVersion &) { +} diff --git a/src/mumble/ServerHandler.cpp b/src/mumble/ServerHandler.cpp index 0506745b3..5f24eeef4 100644 --- a/src/mumble/ServerHandler.cpp +++ b/src/mumble/ServerHandler.cpp @@ -157,7 +157,7 @@ void ServerHandler::udpReady() { quint64 t; pds >> t; accUDP(static_cast<double>(tTimestamp.elapsed() - t) / 1000.0); - } else if (msgType == MessageHandler::UDPVoiceCELT) { + } else if (msgType == MessageHandler::UDPVoiceCELTAlpha) { handleVoicePacket(msgFlags, pds, msgType); } else if (msgType == MessageHandler::UDPVoiceSpeex) { handleVoicePacket(msgFlags, pds, msgType); @@ -335,7 +335,7 @@ void ServerHandler::message(unsigned int msgType, const QByteArray &qbaMsg) { unsigned int msgFlags = ptr[0] & 0x1f; PacketDataStream pds(qbaMsg.constData() + 1, qbaMsg.size()); - if (msgType == MessageHandler::UDPVoiceCELT) + if (msgType == MessageHandler::UDPVoiceCELTAlpha) handleVoicePacket(msgFlags, pds, msgType); else if (msgType == MessageHandler::UDPVoiceSpeex) handleVoicePacket(msgFlags, pds, msgType); diff --git a/src/murmur/Messages.cpp b/src/murmur/Messages.cpp index 4f658a339..36c1799a4 100644 --- a/src/murmur/Messages.cpp +++ b/src/murmur/Messages.cpp @@ -200,6 +200,20 @@ void Server::msgAuthenticate(ServerUser *uSource, MumbleProto::Authenticate &msg userEnterChannel(uSource, lc, true); + if (msg.celt_versions_size() > 0) { + for(int i=0;i < msg.celt_versions_size(); ++i) + uSource->qlCodecs.append(msg.celt_versions(i)); + } else { + uSource->qlCodecs.append(static_cast<qint32>(0x8000000a)); + } + recheckCodecVersions(); + + MumbleProto::CodecVersion mpcv; + mpcv.set_alpha(iCodecAlpha); + mpcv.set_beta(iCodecBeta); + mpcv.set_prefer_alpha(bPreferAlpha); + sendMessage(uSource, mpcv); + // Transmit channel tree QQueue<Channel *> q; QSet<Channel *> chans; @@ -242,7 +256,7 @@ void Server::msgAuthenticate(ServerUser *uSource, MumbleProto::Authenticate &msg // Transmit user profile MumbleProto::UserState mpus; - + uSource->sState = ServerUser::Authenticated; mpus.set_session(uSource->uiSession); mpus.set_name(u8(uSource->qsName)); @@ -1285,3 +1299,6 @@ void Server::msgPermissionQuery(ServerUser *uSource, MumbleProto::PermissionQuer sendClientPermission(uSource, c, true); } + +void Server::msgCodecVersion(ServerUser *, MumbleProto::CodecVersion &) { +} diff --git a/src/murmur/Server.cpp b/src/murmur/Server.cpp index 5dd1a23b0..f074a5872 100644 --- a/src/murmur/Server.cpp +++ b/src/murmur/Server.cpp @@ -101,6 +101,9 @@ Server::Server(int snum, QObject *p) : QThread(p) { hNotify = NULL; #endif qtTimeout = new QTimer(this); + + iCodecAlpha = iCodecBeta = 0; + bPreferAlpha = false; readParams(); initialize(); @@ -655,7 +658,9 @@ void Server::run() { switch (msgType) { case MessageHandler::UDPVoiceSpeex: - case MessageHandler::UDPVoiceCELT: { + case MessageHandler::UDPVoiceCELTAlpha: + case MessageHandler::UDPVoiceCELTBeta: + { u->bUdp = true; processMsg(u, buffer, len); break; @@ -1086,7 +1091,8 @@ void Server::message(unsigned int uiType, const QByteArray &qbaMsg, ServerUser * MessageHandler::UDPMessageType msgType = static_cast<MessageHandler::UDPMessageType>((buffer[0] >> 5) & 0x7); switch (msgType) { - case MessageHandler::UDPVoiceCELT: + case MessageHandler::UDPVoiceCELTAlpha: + case MessageHandler::UDPVoiceCELTBeta: case MessageHandler::UDPVoiceSpeex: processMsg(u, buffer, l); break; @@ -1437,3 +1443,51 @@ bool Server::validateUserName(const QString &name) { bool Server::validateChannelName(const QString &name) { return (qrChannelName.exactMatch(name) && (name.length() <= 512)); } + +void Server::recheckCodecVersions() { + QMap<int, unsigned int> qm; + QMap<int, unsigned int>::const_iterator i; + int users = 0; + foreach(ServerUser *u, qhUsers) { + if (u->qlCodecs.isEmpty()) + continue; + + ++users; + foreach(int version, u->qlCodecs) + ++ qm[version]; + } + + if (! users) + return; + + int version = 0; + int maxu = 0; + i = qm.constEnd(); + do { + --i; + if (i.value() > maxu) { + version = i.key(); + maxu = i.value(); + } + } while (i != qm.constBegin()); + + int cversion = bPreferAlpha ? iCodecAlpha : iCodecBeta; + if (cversion == version) + return; + + MumbleProto::CodecVersion mpcv; + + bPreferAlpha = ! bPreferAlpha; + if (bPreferAlpha) { + iCodecAlpha = version; + mpcv.set_alpha(version); + } else { + iCodecBeta = version; + mpcv.set_beta(version); + } + + mpcv.set_prefer_alpha(bPreferAlpha); + sendAll(mpcv); + + log(QString::fromLatin1("CELT codec switch %1 %2 (prefer %3)").arg(iCodecAlpha,0,16).arg(iCodecBeta,0,16).arg(bPreferAlpha ? iCodecAlpha : iCodecBeta,0,16)); +} diff --git a/src/murmur/Server.h b/src/murmur/Server.h index cfa14325f..9d3fa68ad 100644 --- a/src/murmur/Server.h +++ b/src/murmur/Server.h @@ -146,6 +146,8 @@ class ServerUser : public Connection, public User { HostAddress haAddress; bool bUdp; + + QList<int> qlCodecs; QStringList qslAccessTokens; @@ -210,6 +212,11 @@ class Server : public QThread { bool bValid; void readParams(); + + int iCodecAlpha; + int iCodecBeta; + bool bPreferAlpha; + void recheckCodecVersions(); #ifdef USE_BONJOUR void initBonjour(); |