diff --git a/src/channel.cpp b/src/channel.cpp index dfe8ee70..66ab7ddb 100755 --- a/src/channel.cpp +++ b/src/channel.cpp @@ -157,13 +157,15 @@ void CChannelSet::GetBlockAllConC ( CVector& vecChanID, } void CChannelSet::GetConCliParam ( CVector& vecHostAddresses, - CVector& vecdSamOffs ) + CVector& vecdSamOffs, + CVector& veciJitBufSize ) { CHostAddress InetAddr; /* init return values */ vecHostAddresses.Init ( MAX_NUM_CHANNELS ); - vecdSamOffs.Init ( MAX_NUM_CHANNELS ); + vecdSamOffs.Init ( MAX_NUM_CHANNELS ); + veciJitBufSize.Init ( MAX_NUM_CHANNELS ); /* Check all possible channels */ for ( int i = 0; i < MAX_NUM_CHANNELS; i++ ) @@ -172,7 +174,8 @@ void CChannelSet::GetConCliParam ( CVector& vecHostAddresses, { /* add new address and sample rate offset to vectors */ vecHostAddresses[i] = InetAddr; - vecdSamOffs[i] = vecChannels[i].GetResampleOffset (); + vecdSamOffs[i] = vecChannels[i].GetResampleOffset (); + veciJitBufSize[i] = vecChannels[i].GetSockBufSize (); } } } @@ -244,19 +247,19 @@ bool CChannel::GetAddress(CHostAddress& RetAddr) } } -bool CChannel::PutData(const CVector& vecbyData, - int iNumBytes) +bool CChannel::PutData ( const CVector& vecbyData, + int iNumBytes ) { bool bRet = true; - Mutex.lock(); /* put mutex lock */ + Mutex.lock (); /* put mutex lock */ /* only process if packet has correct size */ - if (iNumBytes == iAudComprSize) + if ( iNumBytes == iAudComprSize ) { /* decompress audio */ - CVector vecsDecomprAudio(BLOCK_SIZE_SAMPLES); - vecsDecomprAudio = AudioCompression.Decode(vecbyData); + CVector vecsDecomprAudio ( BLOCK_SIZE_SAMPLES ); + vecsDecomprAudio = AudioCompression.Decode ( vecbyData ); /* do resampling to compensate for sample rate offsets in the different sound cards of the clients */ @@ -273,20 +276,30 @@ for (int i = 0; i < BLOCK_SIZE_SAMPLES; i++) vecdResOutData[i] = (double) vecsDecomprAudio[i]; - bRet = SockBuf.Put(vecdResOutData); + bRet = SockBuf.Put ( vecdResOutData ); /* reset time-out counter */ iConTimeOut = CON_TIME_OUT_CNT_MAX; } - else if (iNumBytes == 1) + else if ( iNumBytes == 1 ) { /* time stamp packet */ - SampleOffsetEst.AddTimeStampIdx(vecbyData[0]); + SampleOffsetEst.AddTimeStampIdx ( vecbyData[0] ); + } + else + { + + + +// TODO add protocol parsing here +ClientProtocol.ParseMessage ( vecbyData, iNumBytes ); + + + + bRet = false; /* wrong packet size */ } - else - bRet = false; /* wrong packet size */ - Mutex.unlock(); /* put mutex unlock */ + Mutex.unlock (); /* put mutex unlock */ return bRet; } diff --git a/src/channel.h b/src/channel.h index a18c9efc..4d1afec1 100755 --- a/src/channel.h +++ b/src/channel.h @@ -31,7 +31,8 @@ #include "buffer.h" #include "audiocompr.h" #include "util.h" -#include "resample.h" +#include "resample.h" +#include "protocol.h" /* Definitions ****************************************************************/ @@ -115,7 +116,12 @@ protected: CNetBuf SockBuf; /* network output conversion buffer */ - CConvBuf ConvBuf; + CConvBuf ConvBuf; + + +// TEST TODO: better implementation, now this object is created in server AND client which is not good +CClientProtocol ClientProtocol; + /* time stamp index counter */ Q_UINT8 byTimeStampIdxCnt; @@ -143,7 +149,8 @@ public: void GetBlockAllConC(CVector& vecChanID, CVector >& vecvecdData); void GetConCliParam(CVector& vecHostAddresses, - CVector& vecdSamOffs); + CVector& vecdSamOffs, + CVector& veciJitBufSize); /* access functions for actual channels */ bool IsConnected(const int iChanNum) diff --git a/src/llconserverdlg.cpp b/src/llconserverdlg.cpp index 077c5204..6312bb1d 100755 --- a/src/llconserverdlg.cpp +++ b/src/llconserverdlg.cpp @@ -54,7 +54,10 @@ CLlconServerDlg::CLlconServerDlg ( CServer* pNServP, QWidget* parent, ListViewClients->setColumnAlignment(1, Qt::AlignCenter); ListViewClients->addColumn(tr("Get")); ListViewClients->setColumnAlignment(2, Qt::AlignCenter); + ListViewClients->addColumn(tr("Jitter buffer size")); + ListViewClients->setColumnAlignment(3, Qt::AlignRight); ListViewClients->addColumn(tr("Sample-rate offset [Hz]")); + ListViewClients->setColumnAlignment(4, Qt::AlignRight); ListViewClients->clear(); /* insert items in reverse order because in Windows all of them are @@ -106,11 +109,12 @@ void CLlconServerDlg::OnTimer() { CVector vecHostAddresses; CVector vecdSamOffs; + CVector veciJitBufSize; double dCurTiStdDev; ListViewMutex.lock(); - pServer->GetConCliParam(vecHostAddresses, vecdSamOffs); + pServer->GetConCliParam(vecHostAddresses, vecdSamOffs, veciJitBufSize); /* fill list with connected clients */ for (int i = 0; i < MAX_NUM_CHANNELS; i++) @@ -120,11 +124,15 @@ void CLlconServerDlg::OnTimer() /* main text (IP, port number) */ vecpListViewItems[i]->setText(0, QString().sprintf("%s : %d", vecHostAddresses[i].InetAddr.toString().latin1(), - vecHostAddresses[i].iPort) /* IP, port */); + vecHostAddresses[i].iPort) /* IP, port */); + + /* jitter buffer size */ + vecpListViewItems[i]->setText(3, + QString().setNum(veciJitBufSize[i])); /* sample rate offset */ // FIXME disable sample rate estimation result label since estimation does not work -// vecpListViewItems[i]->setText(3, +// vecpListViewItems[i]->setText(4, // QString().sprintf("%5.2f", vecdSamOffs[i])); #ifndef _WIN32 diff --git a/src/protocol.cpp b/src/protocol.cpp index f4f20b8e..bd39e1fa 100755 --- a/src/protocol.cpp +++ b/src/protocol.cpp @@ -7,9 +7,13 @@ Protocol message definition - +-----------+------------+-----------------+--------------+-------------+ - | 2 byte ID | 1 byte cnt | 2 byte length n | n bytes data | 2 bytes CRC | - +-----------+------------+-----------------+--------------+-------------+ + +MAIN FRAME +---------- + + +------------+------------+------------------+--------------+-------------+ + | 2 bytes ID | 1 byte cnt | 2 bytes length n | n bytes data | 2 bytes CRC | + +------------+------------+------------------+--------------+-------------+ - message ID defined by the defines PROTMESSID_x - cnt: counter which is increment for each message and wraps around at 255 @@ -18,6 +22,19 @@ Protocol message definition - 16 bits CRC, calculating over the entire message, is transmitted inverted Generator polynom: G_16(x) = x^16 + x^12 + x^5 + 1, initial state: all ones + +MESSAGES +-------- + +- Jitter buffer size: PROTMESSID_JITT_BUF_SIZE + + +--------------------------+ + | 2 bytes number of blocks | + +--------------------------+ + + + + * ****************************************************************************** * @@ -42,25 +59,62 @@ Protocol message definition /* Implementation *************************************************************/ +bool CClientProtocol::ParseMessage ( const CVector& vecbyData, + const int iNumBytes ) +{ +/* + return code: true -> ok; false -> error +*/ + int iRecCounter, iRecID; + CVector vecData; +// convert unsigned char in uint8_t, TODO convert all buffers in uint8_t +CVector vecbyDataConv ( vecbyData.Size () ); +for ( int i = 0; i < vecbyData.Size (); i++ ) { + vecbyDataConv[i] = static_cast ( vecbyData[i] ); +} + if ( ParseMessageFrame ( vecbyDataConv, iRecCounter, iRecID, vecData ) ) + { + switch ( iRecID ) + { + case PROTMESSID_ACKN: +// TODO implement acknowledge code -> do implementation in CProtocol since +// it can be used in the server protocol, too + break; + } + return true; // everything was ok + } + else + { + return false; // return error code + } +} +void CClientProtocol::CreateJitBufMes ( const int iJitBufSize ) +{ + CVector vecData ( 2 ); + unsigned int iPos = 0; + // build data vector + PutValOnStream ( vecData, iPos, static_cast ( iJitBufSize ), 2 ); - + // build complete message + GenMessageFrame ( vecMessage, iCounter, PROTMESSID_JITT_BUF_SIZE, vecData ); +} /******************************************************************************\ * Message generation (parsing) * \******************************************************************************/ -bool CProtocol::ParseMessage ( const CVector& vecIn, - int& iCnt, - int& iID, - CVector& vecData ) +bool CProtocol::ParseMessageFrame ( const CVector& vecIn, + int& iCnt, + int& iID, + CVector& vecData ) { /* return code: true -> ok; false -> error @@ -143,10 +197,10 @@ uint32_t CProtocol::GetValFromStream ( const CVector& vecIn, return iRet; } -void CProtocol::GenMessage ( CVector& vecOut, - const int iCnt, - const int iID, - const CVector& vecData ) +void CProtocol::GenMessageFrame ( CVector& vecOut, + const int iCnt, + const int iID, + const CVector& vecData ) { int i; diff --git a/src/protocol.h b/src/protocol.h index ec4e3009..3d58c174 100755 --- a/src/protocol.h +++ b/src/protocol.h @@ -41,23 +41,23 @@ #define MESS_LEN_WITHOUT_DATA_BYTE ( MESS_HEADER_LENGTH_BYTE + 2 /* CRC */ ) -/* Classes ********************************************************************/ +/* Classes ********************************************************************/ class CProtocol { public: - CProtocol() : iCounter(0) {} - virtual ~CProtocol() {} + CProtocol () : iCounter ( 0 ) {} + virtual ~CProtocol () {} protected: - bool ParseMessage ( const CVector& vecIn, - int& iCnt, - int& iID, - CVector& vecData ); + bool ParseMessageFrame ( const CVector& vecIn, + int& iCnt, + int& iID, + CVector& vecData ); - void GenMessage ( CVector& vecOut, - const int iCnt, - const int iID, - const CVector& vecData); + void GenMessageFrame ( CVector& vecOut, + const int iCnt, + const int iID, + const CVector& vecData); void PutValOnStream ( CVector& vecIn, unsigned int& iPos, @@ -68,38 +68,44 @@ protected: unsigned int& iPos, const unsigned int iNumOfBytes ); - uint8_t iCounter; + CVector vecMessage; + uint8_t iCounter; }; -class CServerProtocol : public CProtocol -{ -public: - CServerProtocol() {} - virtual ~CServerProtocol() {} - -protected: - -}; class CClientProtocol : public CProtocol { public: - CClientProtocol() {} - virtual ~CClientProtocol() {} + CClientProtocol () {} + virtual ~CClientProtocol () {} + + void CreateJitBufMes ( const int iJitBufSize ); + + bool ParseMessage ( const CVector& vecbyData, + const int iNumBytes ); protected: }; -class CProtMessage + +class CServerProtocol : public CProtocol { public: - CProtMessage () {} - virtual ~CProtMessage () {} + CServerProtocol () {} + virtual ~CServerProtocol () {} + + bool ParseMessage ( const CVector& vecbyData, + const int iNumBytes ); protected: }; - + + + + + + #endif /* !defined(PROTOCOL_H__3B123453_4344_BB2392354455IUHF1912__INCLUDED_) */ diff --git a/src/server.cpp b/src/server.cpp index 22ca0c39..d16af6f8 100755 --- a/src/server.cpp +++ b/src/server.cpp @@ -35,7 +35,13 @@ CServer::CServer () : Socket ( &ChannelSet, this ) /* connect timer timeout signal */ QObject::connect ( &Timer, SIGNAL ( timeout () ), - this, SLOT ( OnTimer () ) ); + this, SLOT ( OnTimer () ) ); + +#ifdef _WIN32 + // event handling of custom events seems not to work under Windows in this + // class, do not use automatic start/stop of server in Windows version + Start (); +#endif } void CServer::Start () @@ -104,7 +110,11 @@ void CServer::OnTimer () { // Disable server if no clients are connected. In this case the server // does not consume any significant CPU when no client is connected. +#ifndef _WIN32 + // event handling of custom events seems not to work under Windows in this + // class, do not use automatic start/stop of server in Windows version Stop (); +#endif } } diff --git a/src/server.h b/src/server.h index c6e31707..c2345228 100755 --- a/src/server.h +++ b/src/server.h @@ -49,8 +49,11 @@ public: void Stop (); bool IsRunning() { return Timer.isActive (); } void GetConCliParam ( CVector& vecHostAddresses, - CVector& vecdSamOffs ) - { ChannelSet.GetConCliParam ( vecHostAddresses, vecdSamOffs ); } + CVector& vecdSamOffs, CVector& veciJitBufSize ) + { + ChannelSet.GetConCliParam ( vecHostAddresses, vecdSamOffs, + veciJitBufSize ); + } bool GetTimingStdDev ( double& dCurTiStdDev ); diff --git a/src/socket.cpp b/src/socket.cpp index ed10b741..1429d85f 100755 --- a/src/socket.cpp +++ b/src/socket.cpp @@ -127,13 +127,9 @@ void CSocket::OnDataReceived () { /* server */ // a packet was received, tell the server object to wake up if it - // is in sleep mode - CLlconEvent* LlconEv = - new CLlconEvent ( MS_PACKET_RECEIVED, 0, 0 ); - - /* Qt will delete the event object when done */ - QThread::postEvent ( pServer, LlconEv ); - + // is in sleep mode (Qt will delete the event object when done) + QThread::postEvent ( pServer, + new CLlconEvent ( MS_PACKET_RECEIVED, 0, 0 ) ); pChannelSet->PutData ( vecbyRecBuf, iNumBytesRead, RecHostAddr ); }