2011-06-12 10:04:14 +02:00
|
|
|
/******************************************************************************\
|
2020-01-01 15:41:43 +01:00
|
|
|
* Copyright (c) 2004-2020
|
2011-06-12 10:04:14 +02:00
|
|
|
*
|
|
|
|
* Author(s):
|
|
|
|
* Volker Fischer
|
|
|
|
*
|
|
|
|
******************************************************************************
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify it under
|
|
|
|
* the terms of the GNU General Public License as published by the Free Software
|
|
|
|
* Foundation; either version 2 of the License, or (at your option) any later
|
|
|
|
* version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
|
|
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
|
|
* details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License along with
|
|
|
|
* this program; if not, write to the Free Software Foundation, Inc.,
|
2020-06-08 22:58:11 +02:00
|
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
2011-06-12 10:04:14 +02:00
|
|
|
*
|
|
|
|
\******************************************************************************/
|
|
|
|
|
|
|
|
#include "channel.h"
|
|
|
|
|
|
|
|
|
|
|
|
// CChannel implementation *****************************************************
|
|
|
|
CChannel::CChannel ( const bool bNIsServer ) :
|
2020-04-13 18:46:04 +02:00
|
|
|
vecdGains ( MAX_NUM_CHANNELS, 1.0 ),
|
2020-05-18 20:46:46 +02:00
|
|
|
vecdPannings ( MAX_NUM_CHANNELS, 0.5 ),
|
2020-06-21 07:16:37 +02:00
|
|
|
iCurSockBufNumFrames ( INVALID_INDEX ),
|
2020-04-13 18:46:04 +02:00
|
|
|
bDoAutoSockBufSize ( true ),
|
|
|
|
iFadeInCnt ( 0 ),
|
|
|
|
iFadeInCntMax ( FADE_IN_NUM_FRAMES_DBLE_FRAMESIZE ),
|
|
|
|
bIsEnabled ( false ),
|
|
|
|
bIsServer ( bNIsServer ),
|
|
|
|
iAudioFrameSizeSamples ( DOUBLE_SYSTEM_FRAME_SIZE_SAMPLES )
|
2011-06-12 10:04:14 +02:00
|
|
|
{
|
2013-02-12 16:34:26 +01:00
|
|
|
// reset network transport properties
|
|
|
|
ResetNetworkTransportProperties();
|
|
|
|
|
2011-06-12 10:04:14 +02:00
|
|
|
// initial value for connection time out counter, we calculate the total
|
|
|
|
// number of samples here and subtract the number of samples of the block
|
|
|
|
// which we take out of the buffer to be independent of block sizes
|
|
|
|
iConTimeOutStartVal = CON_TIME_OUT_SEC_MAX * SYSTEM_SAMPLE_RATE_HZ;
|
|
|
|
|
|
|
|
// init time-out for the buffer with zero -> no connection
|
|
|
|
iConTimeOut = 0;
|
|
|
|
|
|
|
|
// init the socket buffer
|
|
|
|
SetSockBufNumFrames ( DEF_NET_BUF_SIZE_NUM_BL );
|
|
|
|
|
2013-02-11 16:36:47 +01:00
|
|
|
// initialize channel info
|
|
|
|
ResetInfo();
|
2011-06-12 10:04:14 +02:00
|
|
|
|
|
|
|
|
|
|
|
// Connections -------------------------------------------------------------
|
2014-01-29 17:06:52 +01:00
|
|
|
|
|
|
|
// TODO if we later do not fire vectors in the emits, we can remove this again
|
|
|
|
qRegisterMetaType<CVector<uint8_t> > ( "CVector<uint8_t>" );
|
|
|
|
qRegisterMetaType<CHostAddress> ( "CHostAddress" );
|
2014-01-12 10:48:49 +01:00
|
|
|
|
2020-06-06 17:19:25 +02:00
|
|
|
QObject::connect ( &Protocol, &CProtocol::MessReadyForSending,
|
|
|
|
this, &CChannel::OnSendProtMessage );
|
2011-06-12 10:04:14 +02:00
|
|
|
|
2020-06-06 17:19:25 +02:00
|
|
|
QObject::connect ( &Protocol, &CProtocol::ChangeJittBufSize,
|
|
|
|
this, &CChannel::OnJittBufSizeChange );
|
2011-06-12 10:04:14 +02:00
|
|
|
|
2020-06-06 17:19:25 +02:00
|
|
|
QObject::connect ( &Protocol, &CProtocol::ReqJittBufSize,
|
|
|
|
this, &CChannel::ReqJittBufSize );
|
2011-06-12 10:04:14 +02:00
|
|
|
|
2020-06-06 17:19:25 +02:00
|
|
|
QObject::connect ( &Protocol, &CProtocol::ReqChanInfo,
|
|
|
|
this, &CChannel::ReqChanInfo );
|
2011-06-12 10:04:14 +02:00
|
|
|
|
2020-06-06 17:19:25 +02:00
|
|
|
QObject::connect ( &Protocol, &CProtocol::ReqConnClientsList,
|
|
|
|
this, &CChannel::ReqConnClientsList );
|
2011-06-12 10:04:14 +02:00
|
|
|
|
2020-06-06 17:19:25 +02:00
|
|
|
QObject::connect ( &Protocol, &CProtocol::ConClientListMesReceived,
|
|
|
|
this, &CChannel::ConClientListMesReceived );
|
2011-06-12 10:04:14 +02:00
|
|
|
|
2020-06-06 17:19:25 +02:00
|
|
|
QObject::connect ( &Protocol, &CProtocol::ChangeChanGain,
|
|
|
|
this, &CChannel::OnChangeChanGain );
|
2011-06-12 10:04:14 +02:00
|
|
|
|
2020-06-06 17:19:25 +02:00
|
|
|
QObject::connect ( &Protocol, &CProtocol::ChangeChanPan,
|
|
|
|
this, &CChannel::OnChangeChanPan );
|
2020-04-26 00:55:28 +02:00
|
|
|
|
2020-06-06 17:19:25 +02:00
|
|
|
QObject::connect ( &Protocol, &CProtocol::ClientIDReceived,
|
|
|
|
this, &CChannel::ClientIDReceived );
|
2020-05-26 17:28:44 +02:00
|
|
|
|
2020-06-06 17:19:25 +02:00
|
|
|
QObject::connect ( &Protocol, &CProtocol::MuteStateHasChangedReceived,
|
|
|
|
this, &CChannel::MuteStateHasChangedReceived );
|
2020-05-21 11:47:39 +02:00
|
|
|
|
2020-06-06 17:19:25 +02:00
|
|
|
QObject::connect ( &Protocol, &CProtocol::ChangeChanInfo,
|
|
|
|
this, &CChannel::OnChangeChanInfo );
|
2013-02-11 16:36:47 +01:00
|
|
|
|
2020-06-06 17:19:25 +02:00
|
|
|
QObject::connect ( &Protocol, &CProtocol::ChatTextReceived,
|
|
|
|
this, &CChannel::ChatTextReceived );
|
2011-06-12 10:04:14 +02:00
|
|
|
|
2020-06-06 17:19:25 +02:00
|
|
|
QObject::connect ( &Protocol, &CProtocol::NetTranspPropsReceived,
|
|
|
|
this, &CChannel::OnNetTranspPropsReceived );
|
2011-06-12 10:04:14 +02:00
|
|
|
|
2020-06-06 17:19:25 +02:00
|
|
|
QObject::connect ( &Protocol, &CProtocol::ReqNetTranspProps,
|
|
|
|
this, &CChannel::OnReqNetTranspProps );
|
2015-01-23 20:43:18 +01:00
|
|
|
|
2020-06-06 17:19:25 +02:00
|
|
|
QObject::connect ( &Protocol, &CProtocol::LicenceRequired,
|
|
|
|
this, &CChannel::LicenceRequired );
|
2020-04-05 14:49:36 +02:00
|
|
|
|
2020-06-06 17:19:25 +02:00
|
|
|
QObject::connect ( &Protocol, &CProtocol::VersionAndOSReceived,
|
|
|
|
this, &CChannel::VersionAndOSReceived );
|
2020-05-18 21:28:49 +02:00
|
|
|
|
2020-06-14 23:02:13 +02:00
|
|
|
QObject::connect ( &Protocol, &CProtocol::RecorderStateReceived,
|
|
|
|
this, &CChannel::RecorderStateReceived );
|
|
|
|
|
2020-06-06 17:19:25 +02:00
|
|
|
QObject::connect ( &Protocol, &CProtocol::ReqChannelLevelList,
|
|
|
|
this, &CChannel::OnReqChannelLevelList );
|
2011-06-12 10:04:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
bool CChannel::ProtocolIsEnabled()
|
|
|
|
{
|
|
|
|
// for the server, only enable protocol if the channel is connected, i.e.,
|
|
|
|
// successfully audio packets are received from a client
|
|
|
|
// for the client, enable protocol if the channel is enabled, i.e., the
|
|
|
|
// connection button was hit by the user
|
|
|
|
if ( bIsServer )
|
|
|
|
{
|
|
|
|
return IsConnected();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return bIsEnabled;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CChannel::SetEnable ( const bool bNEnStat )
|
|
|
|
{
|
|
|
|
QMutexLocker locker ( &Mutex );
|
|
|
|
|
|
|
|
// set internal parameter
|
|
|
|
bIsEnabled = bNEnStat;
|
|
|
|
|
|
|
|
// if channel is not enabled, reset time out count and protocol
|
|
|
|
if ( !bNEnStat )
|
|
|
|
{
|
|
|
|
iConTimeOut = 0;
|
|
|
|
Protocol.Reset();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-02-16 19:06:18 +01:00
|
|
|
void CChannel::SetAudioStreamProperties ( const EAudComprType eNewAudComprType,
|
2020-04-09 21:26:40 +02:00
|
|
|
const int iNewNetwFrameSize,
|
|
|
|
const int iNewNetwFrameSizeFact,
|
|
|
|
const int iNewNumAudioChannels )
|
2011-06-12 10:04:14 +02:00
|
|
|
{
|
2013-06-03 18:07:17 +02:00
|
|
|
/*
|
2013-12-24 11:00:45 +01:00
|
|
|
this function is intended for the client (not the server)
|
2013-06-03 18:07:17 +02:00
|
|
|
*/
|
|
|
|
CNetworkTransportProps NetworkTransportProps;
|
|
|
|
|
|
|
|
Mutex.lock();
|
|
|
|
{
|
|
|
|
// store new values
|
|
|
|
eAudioCompressionType = eNewAudComprType;
|
|
|
|
iNumAudioChannels = iNewNumAudioChannels;
|
|
|
|
iNetwFrameSize = iNewNetwFrameSize;
|
|
|
|
iNetwFrameSizeFact = iNewNetwFrameSizeFact;
|
2011-06-12 10:04:14 +02:00
|
|
|
|
2020-04-13 18:46:04 +02:00
|
|
|
// update audio frame size
|
|
|
|
if ( eAudioCompressionType == CT_OPUS )
|
|
|
|
{
|
|
|
|
iAudioFrameSizeSamples = DOUBLE_SYSTEM_FRAME_SIZE_SAMPLES;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-04-15 15:29:43 +02:00
|
|
|
iAudioFrameSizeSamples = SYSTEM_FRAME_SIZE_SAMPLES;
|
2020-04-13 18:46:04 +02:00
|
|
|
}
|
|
|
|
|
2014-02-16 21:04:22 +01:00
|
|
|
MutexSocketBuf.lock();
|
|
|
|
{
|
|
|
|
// init socket buffer
|
2020-04-09 21:26:40 +02:00
|
|
|
SockBuf.SetUseDoubleSystemFrameSize ( eAudioCompressionType == CT_OPUS ); // NOTE must be set BEFORE the init()
|
2014-02-16 21:04:22 +01:00
|
|
|
SockBuf.Init ( iNetwFrameSize, iCurSockBufNumFrames );
|
|
|
|
}
|
|
|
|
MutexSocketBuf.unlock();
|
2011-06-12 10:04:14 +02:00
|
|
|
|
2014-02-16 21:04:22 +01:00
|
|
|
MutexConvBuf.lock();
|
|
|
|
{
|
|
|
|
// init conversion buffer
|
|
|
|
ConvBuf.Init ( iNetwFrameSize * iNetwFrameSizeFact );
|
|
|
|
}
|
|
|
|
MutexConvBuf.unlock();
|
2011-06-12 10:04:14 +02:00
|
|
|
|
2013-06-03 18:07:17 +02:00
|
|
|
// fill network transport properties struct
|
2020-04-09 21:26:40 +02:00
|
|
|
NetworkTransportProps = GetNetworkTransportPropsFromCurrentSettings();
|
2013-06-03 18:07:17 +02:00
|
|
|
}
|
|
|
|
Mutex.unlock();
|
2011-06-12 10:04:14 +02:00
|
|
|
|
2013-06-03 18:07:17 +02:00
|
|
|
// tell the server about the new network settings
|
|
|
|
Protocol.CreateNetwTranspPropsMes ( NetworkTransportProps );
|
2011-06-12 10:04:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
bool CChannel::SetSockBufNumFrames ( const int iNewNumFrames,
|
|
|
|
const bool bPreserve )
|
|
|
|
{
|
2013-06-03 18:07:17 +02:00
|
|
|
bool ReturnValue = true; // init with error
|
|
|
|
bool bCurDoAutoSockBufSize = false; // we have to init but init values does not matter
|
2011-06-12 10:04:14 +02:00
|
|
|
|
2013-12-24 11:00:45 +01:00
|
|
|
// first check for valid input parameter range
|
|
|
|
if ( ( iNewNumFrames >= MIN_NET_BUF_SIZE_NUM_BL ) &&
|
|
|
|
( iNewNumFrames <= MAX_NET_BUF_SIZE_NUM_BL ) )
|
2011-06-12 10:04:14 +02:00
|
|
|
{
|
2013-12-24 11:00:45 +01:00
|
|
|
// only apply parameter if new parameter is different from current one
|
|
|
|
if ( iCurSockBufNumFrames != iNewNumFrames )
|
2011-06-12 10:04:14 +02:00
|
|
|
{
|
2014-02-13 22:03:08 +01:00
|
|
|
MutexSocketBuf.lock();
|
2013-06-03 18:07:17 +02:00
|
|
|
{
|
|
|
|
// store new value
|
|
|
|
iCurSockBufNumFrames = iNewNumFrames;
|
2011-06-12 10:04:14 +02:00
|
|
|
|
2013-06-03 18:07:17 +02:00
|
|
|
// the network block size is a multiple of the minimum network
|
|
|
|
// block size
|
|
|
|
SockBuf.Init ( iNetwFrameSize, iNewNumFrames, bPreserve );
|
2011-06-12 10:04:14 +02:00
|
|
|
|
2013-06-03 18:07:17 +02:00
|
|
|
// store current auto socket buffer size setting in the mutex
|
|
|
|
// region since if we use the current parameter below in the
|
|
|
|
// if condition, it may have been changed in between the time
|
|
|
|
// when we have left the mutex region and entered the if
|
|
|
|
// condition
|
|
|
|
bCurDoAutoSockBufSize = bDoAutoSockBufSize;
|
2011-06-12 10:04:14 +02:00
|
|
|
|
2013-06-03 18:07:17 +02:00
|
|
|
ReturnValue = false; // -> no error
|
|
|
|
}
|
2014-02-13 22:03:08 +01:00
|
|
|
MutexSocketBuf.unlock();
|
2011-06-12 10:04:14 +02:00
|
|
|
}
|
|
|
|
}
|
2013-06-03 18:07:17 +02:00
|
|
|
|
|
|
|
// only in case there is no error, we are the server and auto jitter buffer
|
|
|
|
// setting is enabled, we have to report the current setting to the client
|
|
|
|
if ( !ReturnValue && bIsServer && bCurDoAutoSockBufSize )
|
|
|
|
{
|
|
|
|
// we cannot call the "CreateJitBufMes" function directly since
|
|
|
|
// this would give us problems with different threads (e.g. the
|
|
|
|
// timer thread) and the protocol mechanism (problem with
|
|
|
|
// qRegisterMetaType(), etc.)
|
|
|
|
emit ServerAutoSockBufSizeChange ( iNewNumFrames );
|
|
|
|
}
|
2011-06-12 10:04:14 +02:00
|
|
|
|
2013-06-03 18:07:17 +02:00
|
|
|
return ReturnValue; // set error flag
|
2011-06-12 10:04:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void CChannel::SetGain ( const int iChanID,
|
|
|
|
const double dNewGain )
|
|
|
|
{
|
|
|
|
QMutexLocker locker ( &Mutex );
|
|
|
|
|
|
|
|
// set value (make sure channel ID is in range)
|
|
|
|
if ( ( iChanID >= 0 ) && ( iChanID < MAX_NUM_CHANNELS ) )
|
|
|
|
{
|
2020-05-21 11:47:39 +02:00
|
|
|
// signal mute change
|
|
|
|
if ( ( vecdGains[iChanID] == 0 ) && ( dNewGain > 0 ) )
|
|
|
|
{
|
|
|
|
emit MuteStateHasChanged ( iChanID, false );
|
|
|
|
}
|
|
|
|
if ( ( vecdGains[iChanID] > 0 ) && ( dNewGain == 0 ) )
|
|
|
|
{
|
|
|
|
emit MuteStateHasChanged ( iChanID, true );
|
|
|
|
}
|
|
|
|
|
2011-06-12 10:04:14 +02:00
|
|
|
vecdGains[iChanID] = dNewGain;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
double CChannel::GetGain ( const int iChanID )
|
|
|
|
{
|
|
|
|
QMutexLocker locker ( &Mutex );
|
|
|
|
|
|
|
|
// get value (make sure channel ID is in range)
|
|
|
|
if ( ( iChanID >= 0 ) && ( iChanID < MAX_NUM_CHANNELS ) )
|
|
|
|
{
|
|
|
|
return vecdGains[iChanID];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-05-18 20:46:46 +02:00
|
|
|
void CChannel::SetPan ( const int iChanID,
|
|
|
|
const double dNewPan )
|
2020-04-26 00:55:28 +02:00
|
|
|
{
|
|
|
|
QMutexLocker locker ( &Mutex );
|
|
|
|
|
|
|
|
// set value (make sure channel ID is in range)
|
|
|
|
if ( ( iChanID >= 0 ) && ( iChanID < MAX_NUM_CHANNELS ) )
|
|
|
|
{
|
|
|
|
vecdPannings[iChanID] = dNewPan;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-05-18 20:46:46 +02:00
|
|
|
double CChannel::GetPan ( const int iChanID )
|
2020-04-26 00:55:28 +02:00
|
|
|
{
|
|
|
|
QMutexLocker locker ( &Mutex );
|
|
|
|
|
|
|
|
// get value (make sure channel ID is in range)
|
|
|
|
if ( ( iChanID >= 0 ) && ( iChanID < MAX_NUM_CHANNELS ) )
|
|
|
|
{
|
|
|
|
return vecdPannings[iChanID];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-02-11 16:36:47 +01:00
|
|
|
void CChannel::SetChanInfo ( const CChannelCoreInfo& NChanInf )
|
|
|
|
{
|
|
|
|
// apply value (if different from previous one)
|
|
|
|
if ( ChannelInfo != NChanInf )
|
|
|
|
{
|
|
|
|
ChannelInfo = NChanInf;
|
|
|
|
|
|
|
|
// fire message that the channel info has changed
|
|
|
|
emit ChanInfoHasChanged();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-06-12 10:04:14 +02:00
|
|
|
QString CChannel::GetName()
|
|
|
|
{
|
|
|
|
// make sure the string is not written at the same time when it is
|
|
|
|
// read here -> use mutex to secure access
|
|
|
|
QMutexLocker locker ( &Mutex );
|
|
|
|
|
2013-02-11 16:36:47 +01:00
|
|
|
return ChannelInfo.strName;
|
2011-06-12 10:04:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void CChannel::OnSendProtMessage ( CVector<uint8_t> vecMessage )
|
|
|
|
{
|
|
|
|
// only send messages if protocol is enabled, otherwise delete complete
|
|
|
|
// queue
|
|
|
|
if ( ProtocolIsEnabled() )
|
|
|
|
{
|
|
|
|
// emit message to actually send the data
|
|
|
|
emit MessReadyForSending ( vecMessage );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// delete send message queue
|
|
|
|
Protocol.Reset();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CChannel::OnJittBufSizeChange ( int iNewJitBufSize )
|
|
|
|
{
|
|
|
|
// for server apply setting, for client emit message
|
|
|
|
if ( bIsServer )
|
|
|
|
{
|
|
|
|
// first check for special case: auto setting
|
|
|
|
if ( iNewJitBufSize == AUTO_NET_BUF_SIZE_FOR_PROTOCOL )
|
|
|
|
{
|
|
|
|
SetDoAutoSockBufSize ( true );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// manual setting is received, turn OFF auto setting and apply new value
|
|
|
|
SetDoAutoSockBufSize ( false );
|
|
|
|
SetSockBufNumFrames ( iNewJitBufSize, true );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
emit JittBufSizeChanged ( iNewJitBufSize );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CChannel::OnChangeChanGain ( int iChanID,
|
|
|
|
double dNewGain )
|
|
|
|
{
|
|
|
|
SetGain ( iChanID, dNewGain );
|
|
|
|
}
|
|
|
|
|
2020-04-26 00:55:28 +02:00
|
|
|
void CChannel::OnChangeChanPan ( int iChanID,
|
|
|
|
double dNewPan )
|
|
|
|
{
|
2020-05-18 20:46:46 +02:00
|
|
|
SetPan ( iChanID, dNewPan );
|
2020-04-26 00:55:28 +02:00
|
|
|
}
|
|
|
|
|
2013-02-11 16:36:47 +01:00
|
|
|
void CChannel::OnChangeChanInfo ( CChannelCoreInfo ChanInfo )
|
|
|
|
{
|
|
|
|
SetChanInfo ( ChanInfo );
|
|
|
|
}
|
|
|
|
|
2011-06-12 10:04:14 +02:00
|
|
|
bool CChannel::GetAddress ( CHostAddress& RetAddr )
|
|
|
|
{
|
|
|
|
QMutexLocker locker ( &Mutex );
|
|
|
|
|
|
|
|
if ( IsConnected() )
|
|
|
|
{
|
|
|
|
RetAddr = InetAddr;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
RetAddr = CHostAddress();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CChannel::OnNetTranspPropsReceived ( CNetworkTransportProps NetworkTransportProps )
|
|
|
|
{
|
|
|
|
// only the server shall act on network transport properties message
|
|
|
|
if ( bIsServer )
|
|
|
|
{
|
2020-04-04 19:03:19 +02:00
|
|
|
// OPUS and OPUS64 codecs are the only supported codecs right now
|
|
|
|
if ( ( NetworkTransportProps.eAudioCodingType != CT_OPUS ) &&
|
|
|
|
( NetworkTransportProps.eAudioCodingType != CT_OPUS64 ) )
|
2020-03-28 16:27:45 +01:00
|
|
|
{
|
2020-04-06 17:17:49 +02:00
|
|
|
Protocol.CreateOpusSupportedMes();
|
2020-03-28 16:27:45 +01:00
|
|
|
return;
|
|
|
|
}
|
2014-07-26 07:58:01 +02:00
|
|
|
|
2013-02-16 19:06:18 +01:00
|
|
|
Mutex.lock();
|
|
|
|
{
|
|
|
|
// store received parameters
|
|
|
|
eAudioCompressionType = NetworkTransportProps.eAudioCodingType;
|
2019-05-17 22:55:46 +02:00
|
|
|
iNumAudioChannels = static_cast<int> ( NetworkTransportProps.iNumAudioChannels );
|
2013-02-16 19:06:18 +01:00
|
|
|
iNetwFrameSizeFact = NetworkTransportProps.iBlockSizeFact;
|
2019-05-17 22:55:46 +02:00
|
|
|
iNetwFrameSize = static_cast<int> ( NetworkTransportProps.iBaseNetworkPacketSize );
|
2013-02-16 19:06:18 +01:00
|
|
|
|
2020-04-13 18:46:04 +02:00
|
|
|
// update maximum number of frames for fade in counter (only needed for server)
|
|
|
|
// and audio frame size
|
2020-04-13 18:13:42 +02:00
|
|
|
if ( eAudioCompressionType == CT_OPUS )
|
|
|
|
{
|
2020-04-13 19:47:47 +02:00
|
|
|
iFadeInCntMax = FADE_IN_NUM_FRAMES_DBLE_FRAMESIZE / iNetwFrameSizeFact;
|
2020-04-13 18:46:04 +02:00
|
|
|
iAudioFrameSizeSamples = DOUBLE_SYSTEM_FRAME_SIZE_SAMPLES;
|
2020-04-13 18:13:42 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-04-13 19:47:47 +02:00
|
|
|
iFadeInCntMax = FADE_IN_NUM_FRAMES / iNetwFrameSizeFact;
|
2020-04-15 15:29:43 +02:00
|
|
|
iAudioFrameSizeSamples = SYSTEM_FRAME_SIZE_SAMPLES;
|
2020-04-13 18:13:42 +02:00
|
|
|
}
|
|
|
|
|
2020-04-20 22:00:28 +02:00
|
|
|
// the fade-in counter maximum value may have changed, make sure the fade-in counter
|
|
|
|
// is not larger than the allowed maximum value
|
|
|
|
iFadeInCnt = std::min ( iFadeInCnt, iFadeInCntMax );
|
|
|
|
|
2014-02-16 21:04:22 +01:00
|
|
|
MutexSocketBuf.lock();
|
|
|
|
{
|
|
|
|
// update socket buffer (the network block size is a multiple of the
|
2020-04-09 21:26:40 +02:00
|
|
|
// minimum network frame size)
|
|
|
|
SockBuf.SetUseDoubleSystemFrameSize ( eAudioCompressionType == CT_OPUS ); // NOTE must be set BEFORE the init()
|
2014-02-16 21:04:22 +01:00
|
|
|
SockBuf.Init ( iNetwFrameSize, iCurSockBufNumFrames );
|
|
|
|
}
|
|
|
|
MutexSocketBuf.unlock();
|
2013-02-16 19:06:18 +01:00
|
|
|
|
2014-02-16 21:04:22 +01:00
|
|
|
MutexConvBuf.lock();
|
|
|
|
{
|
|
|
|
// init conversion buffer
|
|
|
|
ConvBuf.Init ( iNetwFrameSize * iNetwFrameSizeFact );
|
|
|
|
}
|
|
|
|
MutexConvBuf.unlock();
|
2013-02-16 19:06:18 +01:00
|
|
|
}
|
|
|
|
Mutex.unlock();
|
2011-06-12 10:04:14 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CChannel::OnReqNetTranspProps()
|
|
|
|
{
|
2013-06-03 18:07:17 +02:00
|
|
|
// fill network transport properties struct from current settings and send it
|
|
|
|
Protocol.CreateNetwTranspPropsMes ( GetNetworkTransportPropsFromCurrentSettings() );
|
2011-06-12 10:04:14 +02:00
|
|
|
}
|
|
|
|
|
2013-06-03 18:07:17 +02:00
|
|
|
CNetworkTransportProps CChannel::GetNetworkTransportPropsFromCurrentSettings()
|
2011-06-12 10:04:14 +02:00
|
|
|
{
|
2013-06-03 18:07:17 +02:00
|
|
|
// use current stored settings of the channel to fill the network transport
|
|
|
|
// properties structure
|
2019-05-17 22:55:46 +02:00
|
|
|
return CNetworkTransportProps ( static_cast<uint32_t> ( iNetwFrameSize ),
|
|
|
|
static_cast<uint16_t> ( iNetwFrameSizeFact ),
|
|
|
|
static_cast<uint32_t> ( iNumAudioChannels ),
|
|
|
|
SYSTEM_SAMPLE_RATE_HZ,
|
|
|
|
eAudioCompressionType,
|
|
|
|
0, // version of the codec
|
|
|
|
0 );
|
2011-06-12 10:04:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void CChannel::Disconnect()
|
|
|
|
{
|
|
|
|
// we only have to disconnect the channel if it is actually connected
|
|
|
|
if ( IsConnected() )
|
|
|
|
{
|
|
|
|
// set time out counter to a small value > 0 so that the next time a
|
|
|
|
// received audio block is queried, the disconnection is performed
|
|
|
|
// (assuming that no audio packet is received in the meantime)
|
|
|
|
iConTimeOut = 1; // a small number > 0
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-02-16 09:12:07 +01:00
|
|
|
void CChannel::PutProtcolData ( const int iRecCounter,
|
|
|
|
const int iRecID,
|
|
|
|
const CVector<uint8_t>& vecbyMesBodyData,
|
|
|
|
const CHostAddress& RecHostAddr )
|
2011-06-12 10:04:14 +02:00
|
|
|
{
|
2014-02-16 09:12:07 +01:00
|
|
|
// Only process protocol message if:
|
|
|
|
// - for client only: the packet comes from the server we want to talk to
|
|
|
|
// - the channel is enabled
|
|
|
|
// - the protocol mechanism is enabled
|
|
|
|
if ( ( bIsServer || ( GetAddress() == RecHostAddr ) ) &&
|
|
|
|
IsEnabled() &&
|
|
|
|
ProtocolIsEnabled() )
|
|
|
|
{
|
|
|
|
// parse the message assuming this is a regular protocol message
|
|
|
|
Protocol.ParseMessageBody ( vecbyMesBodyData, iRecCounter, iRecID );
|
|
|
|
}
|
|
|
|
}
|
2013-06-03 18:07:17 +02:00
|
|
|
|
2014-02-16 09:12:07 +01:00
|
|
|
EPutDataStat CChannel::PutAudioData ( const CVector<uint8_t>& vecbyData,
|
|
|
|
const int iNumBytes,
|
|
|
|
CHostAddress RecHostAddr )
|
|
|
|
{
|
2013-06-03 18:07:17 +02:00
|
|
|
// init return state
|
2011-06-12 10:04:14 +02:00
|
|
|
EPutDataStat eRet = PS_GEN_ERROR;
|
|
|
|
|
2014-02-16 09:12:07 +01:00
|
|
|
// Only process audio data if:
|
|
|
|
// - for client only: the packet comes from the server we want to talk to
|
|
|
|
// - the channel is enabled
|
|
|
|
if ( ( bIsServer || ( GetAddress() == RecHostAddr ) ) &&
|
|
|
|
IsEnabled() )
|
2011-06-12 10:04:14 +02:00
|
|
|
{
|
2014-02-16 09:12:07 +01:00
|
|
|
MutexSocketBuf.lock();
|
2011-06-12 10:04:14 +02:00
|
|
|
{
|
2014-02-16 09:12:07 +01:00
|
|
|
// only process audio if packet has correct size
|
|
|
|
if ( iNumBytes == ( iNetwFrameSize * iNetwFrameSizeFact ) )
|
2011-06-12 10:04:14 +02:00
|
|
|
{
|
2014-02-16 09:12:07 +01:00
|
|
|
// store new packet in jitter buffer
|
|
|
|
if ( SockBuf.Put ( vecbyData, iNumBytes ) )
|
2013-06-03 18:07:17 +02:00
|
|
|
{
|
2014-02-16 09:12:07 +01:00
|
|
|
eRet = PS_AUDIO_OK;
|
2013-06-03 18:07:17 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2014-02-16 09:12:07 +01:00
|
|
|
eRet = PS_AUDIO_ERR;
|
2013-06-03 18:07:17 +02:00
|
|
|
}
|
2020-03-29 18:03:24 +02:00
|
|
|
|
|
|
|
// manage audio fade-in counter
|
2020-04-13 18:13:42 +02:00
|
|
|
if ( iFadeInCnt < iFadeInCntMax )
|
2020-03-29 18:03:24 +02:00
|
|
|
{
|
|
|
|
iFadeInCnt++;
|
|
|
|
}
|
2011-06-12 10:04:14 +02:00
|
|
|
}
|
2013-06-03 18:07:17 +02:00
|
|
|
else
|
2011-06-12 10:04:14 +02:00
|
|
|
{
|
2014-02-16 09:12:07 +01:00
|
|
|
// the protocol parsing failed and this was no audio block,
|
|
|
|
// we treat this as protocol error (unkown packet)
|
|
|
|
eRet = PS_PROT_ERR;
|
2011-06-12 10:04:14 +02:00
|
|
|
}
|
|
|
|
|
2014-02-16 09:12:07 +01:00
|
|
|
// All network packets except of valid protocol messages
|
|
|
|
// regardless if they are valid or invalid audio packets lead to
|
|
|
|
// a state change to a connected channel.
|
|
|
|
// This is because protocol messages can only be sent on a
|
|
|
|
// connected channel and the client has to inform the server
|
|
|
|
// about the audio packet properties via the protocol.
|
2011-06-12 10:04:14 +02:00
|
|
|
|
2014-02-16 09:12:07 +01:00
|
|
|
// check if channel was not connected, this is a new connection
|
|
|
|
if ( !IsConnected() )
|
|
|
|
{
|
|
|
|
// overwrite status
|
|
|
|
eRet = PS_NEW_CONNECTION;
|
2020-03-29 18:03:24 +02:00
|
|
|
|
|
|
|
// init audio fade-in counter
|
|
|
|
iFadeInCnt = 0;
|
2011-06-12 10:04:14 +02:00
|
|
|
}
|
|
|
|
|
2014-02-16 09:12:07 +01:00
|
|
|
// reset time-out counter (note that this must be done after the
|
|
|
|
// "IsConnected()" query above)
|
|
|
|
ResetTimeOutCounter();
|
2011-06-12 10:04:14 +02:00
|
|
|
}
|
2014-02-16 09:12:07 +01:00
|
|
|
MutexSocketBuf.unlock();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
eRet = PS_AUDIO_INVALID;
|
2011-06-12 10:04:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return eRet;
|
|
|
|
}
|
|
|
|
|
2014-01-12 10:48:49 +01:00
|
|
|
EGetDataStat CChannel::GetData ( CVector<uint8_t>& vecbyData,
|
|
|
|
const int iNumBytes )
|
2011-06-12 10:04:14 +02:00
|
|
|
{
|
|
|
|
EGetDataStat eGetStatus;
|
|
|
|
|
2014-02-13 22:03:08 +01:00
|
|
|
MutexSocketBuf.lock();
|
2011-06-12 10:04:14 +02:00
|
|
|
{
|
2013-06-03 18:07:17 +02:00
|
|
|
// the socket access must be inside a mutex
|
2014-01-12 10:48:49 +01:00
|
|
|
const bool bSockBufState = SockBuf.Get ( vecbyData, iNumBytes );
|
2013-06-03 18:07:17 +02:00
|
|
|
|
|
|
|
// decrease time-out counter
|
|
|
|
if ( iConTimeOut > 0 )
|
|
|
|
{
|
|
|
|
// subtract the number of samples of the current block since the
|
|
|
|
// time out counter is based on samples not on blocks (definition:
|
|
|
|
// always one atomic block is get by using the GetData() function
|
2020-04-13 18:46:04 +02:00
|
|
|
// where the atomic block size is "iAudioFrameSizeSamples")
|
|
|
|
iConTimeOut -= iAudioFrameSizeSamples;
|
2013-02-12 16:34:26 +01:00
|
|
|
|
2013-06-03 18:07:17 +02:00
|
|
|
if ( iConTimeOut <= 0 )
|
2011-06-12 10:04:14 +02:00
|
|
|
{
|
2013-06-03 18:07:17 +02:00
|
|
|
// channel is just disconnected
|
|
|
|
eGetStatus = GS_CHAN_NOW_DISCONNECTED;
|
|
|
|
iConTimeOut = 0; // make sure we do not have negative values
|
|
|
|
|
|
|
|
// reset network transport properties
|
|
|
|
ResetNetworkTransportProperties();
|
2011-06-12 10:04:14 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2013-06-03 18:07:17 +02:00
|
|
|
if ( bSockBufState )
|
|
|
|
{
|
|
|
|
// everything is ok
|
|
|
|
eGetStatus = GS_BUFFER_OK;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// channel is not yet disconnected but no data in buffer
|
|
|
|
eGetStatus = GS_BUFFER_UNDERRUN;
|
|
|
|
}
|
2011-06-12 10:04:14 +02:00
|
|
|
}
|
|
|
|
}
|
2013-06-03 18:07:17 +02:00
|
|
|
else
|
|
|
|
{
|
|
|
|
// channel is disconnected
|
|
|
|
eGetStatus = GS_CHAN_NOT_CONNECTED;
|
|
|
|
}
|
2011-06-12 10:04:14 +02:00
|
|
|
}
|
2014-02-13 22:03:08 +01:00
|
|
|
MutexSocketBuf.unlock();
|
2013-06-03 18:07:17 +02:00
|
|
|
|
|
|
|
// in case we are just disconnected, we have to fire a message
|
|
|
|
if ( eGetStatus == GS_CHAN_NOW_DISCONNECTED )
|
2011-06-12 10:04:14 +02:00
|
|
|
{
|
2013-06-03 18:07:17 +02:00
|
|
|
// emit message
|
|
|
|
emit Disconnected();
|
2011-06-12 10:04:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return eGetStatus;
|
|
|
|
}
|
|
|
|
|
2014-02-16 09:12:07 +01:00
|
|
|
void CChannel::PrepAndSendPacket ( CHighPrioSocket* pSocket,
|
2014-01-12 10:48:49 +01:00
|
|
|
const CVector<uint8_t>& vecbyNPacket,
|
|
|
|
const int iNPacketLen )
|
2011-06-12 10:04:14 +02:00
|
|
|
{
|
2014-02-13 22:03:08 +01:00
|
|
|
QMutexLocker locker ( &MutexConvBuf );
|
2011-06-12 10:04:14 +02:00
|
|
|
|
|
|
|
// use conversion buffer to convert sound card block size in network
|
|
|
|
// block size
|
2014-01-12 10:48:49 +01:00
|
|
|
if ( ConvBuf.Put ( vecbyNPacket, iNPacketLen ) )
|
2011-06-12 10:04:14 +02:00
|
|
|
{
|
2020-04-05 20:56:05 +02:00
|
|
|
pSocket->SendPacket ( ConvBuf.GetAll(), GetAddress() );
|
2011-06-12 10:04:14 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int CChannel::GetUploadRateKbps()
|
|
|
|
{
|
2020-04-13 18:46:04 +02:00
|
|
|
const int iAudioSizeOut = iNetwFrameSizeFact * iAudioFrameSizeSamples;
|
2011-06-12 10:04:14 +02:00
|
|
|
|
|
|
|
// we assume that the UDP packet which is transported via IP has an
|
2013-03-10 18:32:33 +01:00
|
|
|
// additional header size of ("Network Music Performance (NMP) in narrow
|
|
|
|
// band networks; Carot, Kraemer, Schuller; 2006")
|
2011-06-12 10:04:14 +02:00
|
|
|
// 8 (UDP) + 20 (IP without optional fields) = 28 bytes
|
2013-03-10 18:32:33 +01:00
|
|
|
// 2 (PPP) + 6 (PPPoE) + 18 (MAC) = 26 bytes
|
|
|
|
// 5 (RFC1483B) + 8 (AAL) + 10 (ATM) = 23 bytes
|
|
|
|
return ( iNetwFrameSize * iNetwFrameSizeFact + 28 + 26 + 23 /* header */ ) *
|
2011-06-12 10:04:14 +02:00
|
|
|
8 /* bits per byte */ *
|
|
|
|
SYSTEM_SAMPLE_RATE_HZ / iAudioSizeOut / 1000;
|
|
|
|
}
|
|
|
|
|
2011-06-16 13:36:09 +02:00
|
|
|
void CChannel::UpdateSocketBufferSize()
|
2011-06-12 10:04:14 +02:00
|
|
|
{
|
|
|
|
// just update the socket buffer size if auto setting is enabled, otherwise
|
|
|
|
// do nothing
|
|
|
|
if ( bDoAutoSockBufSize )
|
|
|
|
{
|
2011-06-16 13:36:09 +02:00
|
|
|
// use auto setting result from channel, make sure we preserve the
|
|
|
|
// buffer memory since we just adjust the size here
|
|
|
|
SetSockBufNumFrames ( SockBuf.GetAutoSetting(), true );
|
2011-06-12 10:04:14 +02:00
|
|
|
}
|
|
|
|
}
|