support for OPUS codec
This commit is contained in:
parent
7bed33dab4
commit
0c4f22eaa2
4 changed files with 206 additions and 39 deletions
|
@ -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 );
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
174
src/client.cpp
174
src/client.cpp
|
@ -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 );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 );
|
||||
|
|
Loading…
Reference in a new issue