support for OPUS codec

This commit is contained in:
Volker Fischer 2013-02-16 18:06:18 +00:00
parent 7bed33dab4
commit 0c4f22eaa2
4 changed files with 206 additions and 39 deletions

View file

@ -97,6 +97,11 @@ QObject::connect( &Protocol,
SIGNAL ( PingReceived ( int ) ),
SIGNAL ( PingReceived ( int ) ) );
// #### COMPATIBILITY OLD VERSION, TO BE REMOVED ####
QObject::connect ( &Protocol,
SIGNAL ( OpusSupported() ),
SIGNAL ( OpusSupported() ) );
QObject::connect ( &Protocol,
SIGNAL ( DetectedCLMessage ( CVector<uint8_t>, int ) ),
SIGNAL ( DetectedCLMessage ( CVector<uint8_t>, int ) ) );
@ -141,7 +146,8 @@ void CChannel::SetEnable ( const bool bNEnStat )
}
}
void CChannel::SetAudioStreamProperties ( const int iNewNetwFrameSize,
void CChannel::SetAudioStreamProperties ( const EAudComprType eNewAudComprType,
const int iNewNetwFrameSize,
const int iNewNetwFrameSizeFact,
const int iNewNumAudioChannels )
{
@ -149,9 +155,10 @@ void CChannel::SetAudioStreamProperties ( const int iNewNetwFrameSize,
QMutexLocker locker ( &Mutex );
// store new values
iNumAudioChannels = iNewNumAudioChannels;
iNetwFrameSize = iNewNetwFrameSize;
iNetwFrameSizeFact = iNewNetwFrameSizeFact;
eAudioCompressionType = eNewAudComprType;
iNumAudioChannels = iNewNumAudioChannels;
iNetwFrameSize = iNewNetwFrameSize;
iNetwFrameSizeFact = iNewNetwFrameSizeFact;
// init socket buffer
SockBuf.Init ( iNetwFrameSize, iCurSockBufNumFrames );
@ -346,20 +353,30 @@ void CChannel::OnNetTranspPropsReceived ( CNetworkTransportProps NetworkTranspor
// only the server shall act on network transport properties message
if ( bIsServer )
{
QMutexLocker locker ( &Mutex );
Mutex.lock();
{
// store received parameters
eAudioCompressionType = NetworkTransportProps.eAudioCodingType;
iNumAudioChannels = NetworkTransportProps.iNumAudioChannels;
iNetwFrameSizeFact = NetworkTransportProps.iBlockSizeFact;
iNetwFrameSize =
NetworkTransportProps.iBaseNetworkPacketSize;
// store received parameters
iNumAudioChannels = NetworkTransportProps.iNumAudioChannels;
iNetwFrameSizeFact = NetworkTransportProps.iBlockSizeFact;
iNetwFrameSize =
NetworkTransportProps.iBaseNetworkPacketSize;
// update socket buffer (the network block size is a multiple of the
// minimum network frame size
SockBuf.Init ( iNetwFrameSize, iCurSockBufNumFrames );
// update socket buffer (the network block size is a multiple of the
// minimum network frame size
SockBuf.Init ( iNetwFrameSize, iCurSockBufNumFrames );
// init conversion buffer
ConvBuf.Init ( iNetwFrameSize * iNetwFrameSizeFact );
}
Mutex.unlock();
// init conversion buffer
ConvBuf.Init ( iNetwFrameSize * iNetwFrameSizeFact );
// if old CELT codec is used, inform the client that the new OPUS codec
// is supported
if ( eAudioCompressionType != CT_OPUS )
{
Protocol.CreateOpusSupportedMes();
}
}
}
@ -375,7 +392,7 @@ void CChannel::CreateNetTranspPropsMessFromCurrentSettings()
iNetwFrameSizeFact,
iNumAudioChannels,
SYSTEM_SAMPLE_RATE_HZ,
CT_CELT, // always CELT coding
eAudioCompressionType,
0, // version of the codec
0 );

View file

@ -110,7 +110,8 @@ Protocol.CreateChanNameMes ( ChInfo.strName );
int GetUploadRateKbps();
// set/get network out buffer size and size factor
void SetAudioStreamProperties ( const int iNewNetwFrameSize,
void SetAudioStreamProperties ( const EAudComprType eNewAudComprType,
const int iNewNetwFrameSize,
const int iNewNetwFrameSizeFact,
const int iNewNumAudioChannels );
@ -122,6 +123,7 @@ Protocol.CreateChanNameMes ( ChInfo.strName );
int GetNetwFrameSizeFact() const { return iNetwFrameSizeFact; }
int GetNetwFrameSize() const { return iNetwFrameSize; }
EAudComprType GetAudioCompressionType() { return eAudioCompressionType; }
int GetNumAudioChannels() const { return iNumAudioChannels; }
// network protocol interface
@ -153,10 +155,11 @@ protected:
{
// set it to a state were no decoding is ever possible (since we want
// only to decode data when a network transport property message is
// received with the correct values
iNetwFrameSizeFact = FRAME_SIZE_FACTOR_PREFERRED;
iNetwFrameSize = CELT_MINIMUM_NUM_BYTES;
iNumAudioChannels = 1; // mono
// received with the correct values)
eAudioCompressionType = CT_NONE;
iNetwFrameSizeFact = FRAME_SIZE_FACTOR_PREFERRED;
iNetwFrameSize = CELT_MINIMUM_NUM_BYTES;
iNumAudioChannels = 1; // mono
}
// connection parameters
@ -188,6 +191,7 @@ protected:
int iNetwFrameSizeFact;
int iNetwFrameSize;
EAudComprType eAudioCompressionType;
int iNumAudioChannels;
QMutex Mutex;
@ -212,6 +216,7 @@ signals:
void ConClientListMesReceived ( CVector<CChannelInfo> vecChanInfo );
void ChanInfoHasChanged();
void ReqChanInfo();
void OpusSupported();
void ChatTextReceived ( QString strChatText );
void PingReceived ( int iMs );
void ReqNetTranspProps();

View file

@ -30,6 +30,7 @@ CClient::CClient ( const quint16 iPortNumber ) :
vstrIPAddress ( MAX_NUM_SERVER_ADDR_ITEMS, "" ),
ChannelInfo (),
Channel ( false ), /* we need a client channel -> "false" */
eAudioCompressionType ( CT_OPUS ),
iCeltNumCodedBytes ( CELT_NUM_BYTES_MONO_NORMAL_QUALITY ),
bCeltDoHighQuality ( false ),
bUseStereo ( false ),
@ -75,6 +76,10 @@ CClient::CClient ( const quint16 iPortNumber ) :
1,
&iOpusError );
// we require a constant bit rate
opus_encoder_ctl ( OpusEncoderMono,
OPUS_SET_VBR ( 0 ) );
#ifdef USE_LOW_COMPLEXITY_CELT_ENC
// set encoder low complexity
opus_encoder_ctl ( OpusEncoderMono,
@ -103,6 +108,10 @@ CClient::CClient ( const quint16 iPortNumber ) :
2,
&iOpusError );
// we require a constant bit rate
opus_encoder_ctl ( OpusEncoderStereo,
OPUS_SET_VBR ( 0 ) );
#ifdef USE_LOW_COMPLEXITY_CELT_ENC
// set encoder low complexity
opus_encoder_ctl ( OpusEncoderStereo,
@ -148,6 +157,12 @@ CClient::CClient ( const quint16 iPortNumber ) :
SIGNAL ( ChatTextReceived ( QString ) ),
SIGNAL ( ChatTextReceived ( QString ) ) );
// #### COMPATIBILITY OLD VERSION, TO BE REMOVED ####
QObject::connect ( &Channel, SIGNAL ( OpusSupported() ),
this, SLOT ( OnOpusSupported() ) );
QObject::connect ( &ConnLessProtocol,
SIGNAL ( CLMessReadyForSending ( CHostAddress, CVector<uint8_t> ) ),
this, SLOT ( OnSendCLProtMessage ( CHostAddress, CVector<uint8_t> ) ) );
@ -334,6 +349,36 @@ void CClient::SetSndCrdPrefFrameSizeFactor ( const int iNewFactor )
}
}
// #### COMPATIBILITY OLD VERSION, TO BE REMOVED ####
void CClient::OnOpusSupported()
{
if ( eAudioCompressionType != CT_OPUS )
{
SetAudoCompressiontype ( CT_OPUS );
}
}
// #### COMPATIBILITY OLD VERSION, TO BE REMOVED ####
void CClient::SetAudoCompressiontype ( const EAudComprType eNAudCompressionType )
{
// init with new parameter, if client was running then first
// stop it and restart again after new initialization
const bool bWasRunning = Sound.IsRunning();
if ( bWasRunning )
{
Sound.Stop();
}
// set new parameter
eAudioCompressionType = eNAudCompressionType;
Init();
if ( bWasRunning )
{
Sound.Start();
}
}
void CClient::SetCELTHighQuality ( const bool bNCeltHighQualityFlag )
{
// init with new parameter, if client was running then first
@ -518,6 +563,11 @@ void CClient::OnSndCrdReinitRequest ( int iSndCrdResetType )
void CClient::Start()
{
// #### COMPATIBILITY OLD VERSION, TO BE REMOVED ####
// our first attempt is always to use the old code
eAudioCompressionType = CT_CELT;
// init object
Init();
@ -674,6 +724,22 @@ void CClient::Init()
}
vecCeltData.Init ( iCeltNumCodedBytes );
// calculate and set the bit rate
const int iCeltBitRateBitsPerSec =
( SYSTEM_SAMPLE_RATE_HZ * iCeltNumCodedBytes * 8 ) /
SYSTEM_FRAME_SIZE_SAMPLES;
if ( bUseStereo )
{
opus_encoder_ctl ( OpusEncoderStereo,
OPUS_SET_BITRATE ( iCeltBitRateBitsPerSec ) );
}
else
{
opus_encoder_ctl ( OpusEncoderMono,
OPUS_SET_BITRATE ( iCeltBitRateBitsPerSec ) );
}
// inits for network and channel
vecbyNetwData.Init ( iCeltNumCodedBytes );
if ( bUseStereo )
@ -681,7 +747,8 @@ void CClient::Init()
vecsNetwork.Init ( iStereoBlockSizeSam );
// set the channel network properties
Channel.SetAudioStreamProperties ( iCeltNumCodedBytes,
Channel.SetAudioStreamProperties ( eAudioCompressionType,
iCeltNumCodedBytes,
iSndCrdFrameSizeFactor,
2 );
}
@ -690,7 +757,8 @@ void CClient::Init()
vecsNetwork.Init ( iMonoBlockSizeSam );
// set the channel network properties
Channel.SetAudioStreamProperties ( iCeltNumCodedBytes,
Channel.SetAudioStreamProperties ( eAudioCompressionType,
iCeltNumCodedBytes,
iSndCrdFrameSizeFactor,
1 );
}
@ -892,21 +960,43 @@ void CClient::ProcessAudioDataIntern ( CVector<int16_t>& vecsStereoSndCrd )
{
if ( bUseStereo )
{
// encode current audio frame with CELT encoder
cc6_celt_encode ( CeltEncoderStereo,
// encode current audio frame
if ( eAudioCompressionType == CT_CELT )
{
cc6_celt_encode ( CeltEncoderStereo,
&vecsNetwork[i * 2 * SYSTEM_FRAME_SIZE_SAMPLES],
NULL,
&vecCeltData[0],
iCeltNumCodedBytes );
}
else
{
opus_encode ( OpusEncoderStereo,
&vecsNetwork[i * 2 * SYSTEM_FRAME_SIZE_SAMPLES],
NULL,
SYSTEM_FRAME_SIZE_SAMPLES,
&vecCeltData[0],
iCeltNumCodedBytes );
}
}
else
{
// encode current audio frame with CELT encoder
cc6_celt_encode ( CeltEncoderMono,
// encode current audio frame
if ( eAudioCompressionType == CT_CELT )
{
cc6_celt_encode ( CeltEncoderMono,
&vecsNetwork[i * SYSTEM_FRAME_SIZE_SAMPLES],
NULL,
&vecCeltData[0],
iCeltNumCodedBytes );
}
else
{
opus_encode ( OpusEncoderMono,
&vecsNetwork[i * SYSTEM_FRAME_SIZE_SAMPLES],
NULL,
SYSTEM_FRAME_SIZE_SAMPLES,
&vecCeltData[0],
iCeltNumCodedBytes );
}
}
// send coded audio through the network
@ -936,17 +1026,41 @@ void CClient::ProcessAudioDataIntern ( CVector<int16_t>& vecsStereoSndCrd )
{
if ( bUseStereo )
{
cc6_celt_decode ( CeltDecoderStereo,
if ( eAudioCompressionType == CT_CELT )
{
cc6_celt_decode ( CeltDecoderStereo,
&vecbyNetwData[0],
iCeltNumCodedBytes,
&vecsStereoSndCrd[i * 2 * SYSTEM_FRAME_SIZE_SAMPLES] );
}
else
{
opus_decode ( OpusDecoderStereo,
&vecbyNetwData[0],
iCeltNumCodedBytes,
&vecsStereoSndCrd[i * 2 * SYSTEM_FRAME_SIZE_SAMPLES] );
&vecsStereoSndCrd[i * 2 * SYSTEM_FRAME_SIZE_SAMPLES],
SYSTEM_FRAME_SIZE_SAMPLES,
0 );
}
}
else
{
cc6_celt_decode ( CeltDecoderMono,
if ( eAudioCompressionType == CT_CELT )
{
cc6_celt_decode ( CeltDecoderMono,
&vecbyNetwData[0],
iCeltNumCodedBytes,
&vecsAudioSndCrdMono[i * SYSTEM_FRAME_SIZE_SAMPLES] );
}
else
{
opus_decode ( OpusDecoderMono,
&vecbyNetwData[0],
iCeltNumCodedBytes,
&vecsAudioSndCrdMono[i * SYSTEM_FRAME_SIZE_SAMPLES] );
&vecsAudioSndCrdMono[i * SYSTEM_FRAME_SIZE_SAMPLES],
SYSTEM_FRAME_SIZE_SAMPLES,
0 );
}
}
}
else
@ -954,17 +1068,41 @@ void CClient::ProcessAudioDataIntern ( CVector<int16_t>& vecsStereoSndCrd )
// lost packet
if ( bUseStereo )
{
cc6_celt_decode ( CeltDecoderStereo,
if ( eAudioCompressionType == CT_CELT )
{
cc6_celt_decode ( CeltDecoderStereo,
NULL,
0,
&vecsStereoSndCrd[i * 2 * SYSTEM_FRAME_SIZE_SAMPLES] );
}
else
{
opus_decode ( OpusDecoderStereo,
NULL,
0,
&vecsStereoSndCrd[i * 2 * SYSTEM_FRAME_SIZE_SAMPLES] );
iCeltNumCodedBytes,
&vecsStereoSndCrd[i * 2 * SYSTEM_FRAME_SIZE_SAMPLES],
SYSTEM_FRAME_SIZE_SAMPLES,
0 );
}
}
else
{
cc6_celt_decode ( CeltDecoderMono,
if ( eAudioCompressionType == CT_CELT )
{
cc6_celt_decode ( CeltDecoderMono,
NULL,
0,
&vecsAudioSndCrdMono[i * SYSTEM_FRAME_SIZE_SAMPLES] );
}
else
{
opus_decode ( OpusDecoderMono,
NULL,
0,
&vecsAudioSndCrdMono[i * SYSTEM_FRAME_SIZE_SAMPLES] );
iCeltNumCodedBytes,
&vecsAudioSndCrdMono[i * SYSTEM_FRAME_SIZE_SAMPLES],
SYSTEM_FRAME_SIZE_SAMPLES,
0 );
}
}
}
}

View file

@ -261,6 +261,9 @@ protected:
int EvaluatePingMessage ( const int iMs );
void CreateServerJitterBufferMessage();
// #### COMPATIBILITY OLD VERSION, TO BE REMOVED ####
void SetAudoCompressiontype ( const EAudComprType eNAudCompressionType );
// only one channel is needed for client application
CChannel Channel;
CProtocol ConnLessProtocol;
@ -276,6 +279,7 @@ protected:
OpusDecoder* OpusDecoderMono;
OpusEncoder* OpusEncoderStereo;
OpusDecoder* OpusDecoderStereo;
EAudComprType eAudioCompressionType;
int iCeltNumCodedBytes;
bool bCeltDoHighQuality;
bool bUseStereo;
@ -342,6 +346,9 @@ public slots:
void OnSndCrdReinitRequest ( int iSndCrdResetType );
// #### COMPATIBILITY OLD VERSION, TO BE REMOVED ####
void OnOpusSupported();
signals:
void ConClientListNameMesReceived ( CVector<CChannelInfo> vecChanInfo );
void ConClientListMesReceived ( CVector<CChannelInfo> vecChanInfo );