diff --git a/ambed/cambepacket.h b/ambed/cambepacket.h index 13cd124..f6ae00a 100644 --- a/ambed/cambepacket.h +++ b/ambed/cambepacket.h @@ -48,6 +48,9 @@ public: // destructor virtual ~CAmbePacket(); + // identity + bool IsAmbe(void) const { return true; } + // get uint8 GetCodec(void) const { return m_uiCodec; } uint8 *GetAmbe(void) { return m_uiAmbe; } diff --git a/ambed/cpacket.h b/ambed/cpacket.h index cd30d6a..a7768c0 100644 --- a/ambed/cpacket.h +++ b/ambed/cpacket.h @@ -40,13 +40,17 @@ public: // destructor virtual ~CPacket() {}; + // identity + virtual bool IsVoice(void) const { return false; } + virtual bool IsAmbe(void) const { return false; } + // get - int GetChannel(void) const { return m_iCh; } - uint8 GetPid(void) const { return m_uiPid; } + int GetChannel(void) const { return m_iCh; } + uint8 GetPid(void) const { return m_uiPid; } // set - void SetChannel(int i) { m_iCh = i; } - void SetPid(uint8 ui) { m_uiPid = ui; } + void SetChannel(int i) { m_iCh = i; } + void SetPid(uint8 ui) { m_uiPid = ui; } protected: // data diff --git a/ambed/cusb3003interface.h b/ambed/cusb3003interface.h index 2be4f57..984130e 100644 --- a/ambed/cusb3003interface.h +++ b/ambed/cusb3003interface.h @@ -70,6 +70,7 @@ protected: bool OpenDevice(void); bool ResetDevice(void); bool ConfigureDevice(void); + int GetDeviceFifoSize(void) const { return 2; } // data uint8 m_uiChCodecs[USB3003_NB_CH]; diff --git a/ambed/cusb3xxxinterface.cpp b/ambed/cusb3xxxinterface.cpp index 7bf3fdd..c8eb461 100644 --- a/ambed/cusb3xxxinterface.cpp +++ b/ambed/cusb3xxxinterface.cpp @@ -39,12 +39,12 @@ CUsb3xxxInterface::CUsb3xxxInterface(uint32 uiVid, uint32 uiPid, const char *szDeviceName, const char *szDeviceSerial) { m_FtdiHandle = NULL; - m_iDeviceFifoLevel = 0; - m_iActiveQueue = QUEUE_CHANNEL; m_uiVid = uiVid; m_uiPid = uiPid; ::strcpy(m_szDeviceName, szDeviceName); ::strcpy(m_szDeviceSerial, szDeviceSerial); + m_iSpeechFifolLevel = 0; + m_iChannelFifolLevel = 0; } //////////////////////////////////////////////////////////////////////////////////////// @@ -52,6 +52,19 @@ CUsb3xxxInterface::CUsb3xxxInterface(uint32 uiVid, uint32 uiPid, const char *szD CUsb3xxxInterface::~CUsb3xxxInterface() { + // delete m_SpeechQueues + for ( int i = 0; i < m_SpeechQueues.size(); i++ ) + { + delete m_SpeechQueues[i]; + } + m_SpeechQueues.clear(); + + // delete m_ChannelQueues + for ( int i = 0; i < m_ChannelQueues.size(); i++ ) + { + delete m_ChannelQueues[i]; + } + m_ChannelQueues.clear(); } //////////////////////////////////////////////////////////////////////////////////////// @@ -82,6 +95,13 @@ bool CUsb3xxxInterface::Init(void) } std::cout << std::endl; + // create our queues + for ( int i = 0; i < GetNbChannels(); i++ ) + { + m_SpeechQueues.push_back(new CPacketQueue); + m_ChannelQueues.push_back(new CPacketQueue); + } + // base class if ( ok ) { @@ -118,11 +138,10 @@ void CUsb3xxxInterface::Task(void) { if ( IsValidSpeechPacket(Buffer, &iCh, &VoicePacket) ) { -#ifdef DEBUG_DUMPFILE - g_AmbeServer.m_DebugFile << m_szDeviceName << "\t" << "->Sp" << iCh << std::endl; std::cout.flush(); -#endif - // update fifo status - m_iDeviceFifoLevel = MAX(m_iDeviceFifoLevel-1, 0); + // update fifo level + // as we get a speech packet, it means that the device + // channel fifo input decreased by 1 + m_iChannelFifolLevel = MAX(0, m_iChannelFifolLevel-1); // push back to relevant channel voice queue // our incoming channel packet has now been through the decoder @@ -140,13 +159,14 @@ void CUsb3xxxInterface::Task(void) } else if ( IsValidChannelPacket(Buffer, &iCh, &AmbePacket) ) { -#ifdef DEBUG_DUMPFILE - g_AmbeServer.m_DebugFile << m_szDeviceName << "\t" << "->Ch" << iCh << std::endl; std::cout.flush(); -#endif - // update fifo status - m_iDeviceFifoLevel = MAX(m_iDeviceFifoLevel-1, 0); - + // update fifo level + // as we get a channel packet, it means that the device + // speech fifo input decreased by 1 + m_iSpeechFifolLevel = MAX(0, m_iSpeechFifolLevel-1); + // push back to relevant channel outcoming queue + // we are done with this packet transcoding + // it's final step Channel = GetChannelWithChannelOut(iCh); if ( Channel != NULL ) { @@ -178,9 +198,12 @@ void CUsb3xxxInterface::Task(void) // get packet CVoicePacket *Packet = (CVoicePacket *)Queue->front(); Queue->pop(); + // this is second step of transcoding + // we just received from hardware a decoded speech packet // post it to relevant channel encoder - Packet->SetChannel(Channel->GetChannelOut()); - m_SpeechQueue.push(Packet); + int i = Channel->GetChannelOut(); + Packet->SetChannel(i); + m_SpeechQueues[i]->push(Packet); // done done = false; } @@ -196,9 +219,12 @@ void CUsb3xxxInterface::Task(void) // get packet CAmbePacket *Packet = (CAmbePacket *)Queue->front(); Queue->pop(); + // this is first step of transcoding + // a fresh new packet to be transcoded is showing up // post it to relevant channel decoder - Packet->SetChannel(Channel->GetChannelIn()); - m_ChannelQueue.push(Packet); + int i = Channel->GetChannelIn(); + Packet->SetChannel(i); + m_ChannelQueues[i]->push(Packet); // done done = false; } @@ -207,57 +233,94 @@ void CUsb3xxxInterface::Task(void) } } while (!done); - // process device incoming queues + // process device incoming queues (aka to device) // interlace speech and channels packets - // and make sure that the fifo is always - // fed. - unsigned long iQueueLevel = m_SpeechQueue.size() + m_ChannelQueue.size(); - if ( ((m_iDeviceFifoLevel == 0) && (iQueueLevel >= 2)) || (m_iDeviceFifoLevel == 1) ) + // and post to final device queue + do { - if ( m_iActiveQueue == QUEUE_CHANNEL ) + done = true; + // loop on all channels + for ( int i = 0; i < GetNbChannels(); i++ ) { - // post next channel packet - if ( !m_ChannelQueue.empty() ) + // speech + if ( !m_SpeechQueues[i]->empty() ) { // get packet - CAmbePacket *Packet = (CAmbePacket *)m_ChannelQueue.front(); - m_ChannelQueue.pop(); - //Post it - EncodeChannelPacket(&Buffer, Packet->GetChannel(), Packet); - WriteBuffer(Buffer); - m_iDeviceFifoLevel++; - // and delete it -#ifdef DEBUG_DUMPFILE - g_AmbeServer.m_DebugFile << m_szDeviceName << "\t" << "Ch" << Packet->GetChannel() << "->" << std::endl; std::cout.flush(); -#endif - delete Packet; - } - // and interlace - m_iActiveQueue = QUEUE_SPEECH; - } - else - { - // post next speech packet - if ( !m_SpeechQueue.empty() ) - { - // get packet - CVoicePacket *Packet = (CVoicePacket *)m_SpeechQueue.front(); - m_SpeechQueue.pop(); - //Post it - EncodeSpeechPacket(&Buffer, Packet->GetChannel(), Packet); - WriteBuffer(Buffer); - m_iDeviceFifoLevel++; - // and delete it -#ifdef DEBUG_DUMPFILE - g_AmbeServer.m_DebugFile << m_szDeviceName << "\t" << "Sp" << Packet->GetChannel() << "->" << std::endl; std::cout.flush(); -#endif - delete Packet; + CPacket *Packet = m_SpeechQueues[i]->front(); + m_SpeechQueues[i]->pop(); + // and push to device queue + m_DeviceQueue.push(Packet); + // next + done = false; + } + // ambe + if ( !m_ChannelQueues[i]->empty() ) + { + // get packet + CPacket *Packet = m_ChannelQueues[i]->front(); + m_ChannelQueues[i]->pop(); + // and push to device queue + m_DeviceQueue.push(Packet); + // done = false; } - // and interlace - m_iActiveQueue = QUEUE_CHANNEL; } - } + + } while (!done); + // process device queue to feed hardware + // make sure that device fifo is fed all the time + int fifoSize = GetDeviceFifoSize(); + do + { + done = true; + // if device fifo level is zero (device idle) + // wait that at least 3 packets are in incoming + // queue before restarting + if ( ((m_iSpeechFifolLevel+m_iChannelFifolLevel) > 0) || (m_DeviceQueue.size() >= (fifoSize+1)) ) + { + // any packet to send ? + if ( m_DeviceQueue.size() > 0 ) + { + // yes, get it + CPacket *Packet = m_DeviceQueue.front(); + if ( Packet->IsVoice() && (m_iSpeechFifolLevel < fifoSize) ) + { + // encode & post + EncodeSpeechPacket(&Buffer, Packet->GetChannel(), (CVoicePacket *)Packet); + WriteBuffer(Buffer); + // remove from queue + m_DeviceQueue.pop(); + // and delete it + delete Packet; + // update fifo level + m_iSpeechFifolLevel++; + // next + done = false; +#ifdef DEBUG_DUMPFILE + g_AmbeServer.m_DebugFile << m_szDeviceName << "\t" << "Sp" << Packet->GetChannel() << "->" << std::endl; std::cout.flush(); +#endif + } + else if ( Packet->IsAmbe() && (m_iChannelFifolLevel < fifoSize) ) + { + // encode & post + EncodeChannelPacket(&Buffer, Packet->GetChannel(), (CAmbePacket *)Packet); + WriteBuffer(Buffer); + // remove from queue + m_DeviceQueue.pop(); + // and delete it + delete Packet; + // update fifo level + m_iChannelFifolLevel++; + // next + done = false; +#ifdef DEBUG_DUMPFILE + g_AmbeServer.m_DebugFile << m_szDeviceName << "\t" << "Ch" << Packet->GetChannel() << "->" << std::endl; std::cout.flush(); +#endif + } + + } + } + } while (!done); // and wait a bit CTimePoint::TaskSleepFor(2); diff --git a/ambed/cusb3xxxinterface.h b/ambed/cusb3xxxinterface.h index 31bf3c4..d7dd3cf 100644 --- a/ambed/cusb3xxxinterface.h +++ b/ambed/cusb3xxxinterface.h @@ -98,12 +98,13 @@ protected: virtual void EncodeSpeechPacket(CBuffer *, int, CVoicePacket *) {} // low level - virtual bool OpenDevice(void) { return false; } - virtual bool ResetDevice(void) { return false; } + virtual bool OpenDevice(void) { return false; } + virtual bool ResetDevice(void) { return false; } bool ReadDeviceVersion(void); bool DisableParity(void); - virtual bool ConfigureDevice(void) { return false; } + virtual bool ConfigureDevice(void) { return false; } bool ConfigureChannel(uint8, const uint8 *, int, int); + virtual int GetDeviceFifoSize(void) const { return 1; } // io level bool ReadBuffer(CBuffer *); @@ -117,17 +118,18 @@ protected: protected: // data - uint32 m_uiVid; - uint32 m_uiPid; - char m_szDeviceName[FTDI_MAX_STRINGLENGTH]; - char m_szDeviceSerial[FTDI_MAX_STRINGLENGTH]; - FT_HANDLE m_FtdiHandle; + uint32 m_uiVid; + uint32 m_uiPid; + char m_szDeviceName[FTDI_MAX_STRINGLENGTH]; + char m_szDeviceSerial[FTDI_MAX_STRINGLENGTH]; + FT_HANDLE m_FtdiHandle; // queue - CPacketQueue m_SpeechQueue; - CPacketQueue m_ChannelQueue; - int m_iDeviceFifoLevel; - int m_iActiveQueue; + std::vector m_SpeechQueues; + std::vector m_ChannelQueues; + CPacketQueue m_DeviceQueue; + int m_iSpeechFifolLevel; + int m_iChannelFifolLevel; }; //////////////////////////////////////////////////////////////////////////////////////// diff --git a/ambed/cvoicepacket.h b/ambed/cvoicepacket.h index 7189d01..7dbefc3 100644 --- a/ambed/cvoicepacket.h +++ b/ambed/cvoicepacket.h @@ -47,7 +47,10 @@ public: // destructor virtual ~CVoicePacket(); - + + // identity + bool IsVoice(void) const { return true; } + // get uint8 *GetVoice(void) { return m_uiVoice; } int GetVoiceSize(void) const { return m_iSize; } diff --git a/ambed/main.h b/ambed/main.h index 08f3221..3c7bd19 100644 --- a/ambed/main.h +++ b/ambed/main.h @@ -48,8 +48,8 @@ // version ----------------------------------------------------- #define VERSION_MAJOR 1 -#define VERSION_MINOR 2 -#define VERSION_REVISION 1 +#define VERSION_MINOR 3 +#define VERSION_REVISION 0 // global ------------------------------------------------------ diff --git a/ambed/readme b/ambed/readme index 9d74345..4224cca 100644 --- a/ambed/readme +++ b/ambed/readme @@ -22,6 +22,7 @@ // along with Foobar. If not, see . // ---------------------------------------------------------------------------- +VERSION: 1.3.0 Hardware compatibility. ====================== @@ -37,13 +38,13 @@ This version of ambed is compatible with: Available transcoding channels per device: device DMR->DSTAR DSTAR->DMR Nb Of concurrent channels ----------------------------------------------------------------------- +------------------------------------------------------------------------- 3000(pair) 1 1 2 -3003 1 1 1 -3003(pair) 3 3 not tested +3003 1 1 2 +3003(pair) 3 3 4 3003-3000(pair) 2 2 not tested -3006 3 3 4 -3012 6 6 8 +3006 3 3 6 +3012 6 6 12 Multiple devices can be used at the same time. You need to use 3000 by pairs or paired with a 3003 diff --git a/ambedtest/ccodecstream.cpp b/ambedtest/ccodecstream.cpp index 5910f8d..5c5fcf3 100644 --- a/ambedtest/ccodecstream.cpp +++ b/ambedtest/ccodecstream.cpp @@ -45,6 +45,7 @@ CCodecStream::CCodecStream(uint16 uiId, uint8 uiCodecIn, uint8 uiCodecOut) m_bConnected = false; m_iAmbeSrcPtr = 0; m_iAmbeDestPtr = 0; + m_uiNbTotalPacketSent = 0; m_uiNbPacketSent = 0; m_uiNbPacketReceived = 0; m_uiNbPacketBad = 0; @@ -120,6 +121,7 @@ bool CCodecStream::Init(uint16 uiPort) m_pThread = new std::thread(CCodecStream::Thread, this); m_bConnected = true; m_FrameTimer.Now(); + m_uiNbTotalPacketSent = 0; ResetStats(); } else @@ -181,11 +183,12 @@ void CCodecStream::Task(void) // and increment pointer m_iAmbeSrcPtr = (m_iAmbeSrcPtr + 1) % m_AmbeSrc.size(); + m_uiNbTotalPacketSent++; m_uiNbPacketSent++; }*/ // any packt to send to trancoder ? - uint32 uiNbPacketToSend = (uint32)(m_FrameTimer.DurationSinceNow() * 50.0) - m_uiNbPacketSent; + uint32 uiNbPacketToSend = (uint32)(m_FrameTimer.DurationSinceNow() * 50.0) - m_uiNbTotalPacketSent; if ( uiNbPacketToSend > 0 ) { for ( int i = 0; i < uiNbPacketToSend; i++ ) @@ -196,6 +199,7 @@ void CCodecStream::Task(void) // and increment pointer m_iAmbeSrcPtr = (m_iAmbeSrcPtr + 1) % m_AmbeSrc.size(); + m_uiNbTotalPacketSent++; m_uiNbPacketSent++; } } @@ -283,15 +287,19 @@ void CCodecStream::ResetStats(void) void CCodecStream::DisplayStats(void) { - //double fps = (double)m_uiNbPacketSent / m_StatsTimer.DurationSinceNow(); - double fps = (double)m_uiNbPacketReceived / m_StatsTimer.DurationSinceNow(); + // get stats + uint32 uiSent = m_uiNbPacketSent; + uint32 uiReceived = m_uiNbPacketReceived; + uint32 uiBad = m_uiNbPacketBad; + double fps = (double)uiReceived / m_StatsTimer.DurationSinceNow(); - std::cout << "Stream " << (int)m_uiStreamId << " (" << (int)m_uiCodecIn << "->" << (int)m_uiCodecOut << ") : "; - std::cout << m_uiNbPacketSent << " / " << m_uiNbPacketReceived << " / " << m_uiNbPacketTimeout; - //std::cout << " / " << m_uiNbPacketBad; - std::cout << " ; " << fps << " fps"; + // resets + ResetStats(); - std::cout << std::endl; - - m_uiNbPacketBad = 0; + // displays + char sz[256]; + sprintf(sz, "Stream %d (%d->%d) : %u / %u / %u : %.1f fps", + m_uiStreamId, m_uiCodecIn, m_uiCodecOut, + uiSent, uiReceived, uiBad, fps); + std::cout << sz << std::endl; } diff --git a/ambedtest/ccodecstream.h b/ambedtest/ccodecstream.h index 568e466..4619648 100644 --- a/ambedtest/ccodecstream.h +++ b/ambedtest/ccodecstream.h @@ -99,6 +99,7 @@ protected: std::thread *m_pThread; CTimePoint m_TimeoutTimer; CTimePoint m_FrameTimer; + uint32 m_uiNbTotalPacketSent; // stats CTimePoint m_StatsTimer; diff --git a/ambedtest/makefile b/ambedtest/makefile index bc1a804..c85fe4c 100644 --- a/ambedtest/makefile +++ b/ambedtest/makefile @@ -8,10 +8,10 @@ EXECUTABLE=ambedtest all: $(SOURCES) $(EXECUTABLE) $(EXECUTABLE): $(OBJECTS) - $(CC) $(LDFLAGS) $(OBJECTS) -Wl,-rpath,/usr/local/lib -o $@ + $(CC) $(LDFLAGS) $(OBJECTS) -lftd2xx -Wl,-rpath,/usr/local/lib -o $@ .cpp.o: $(CC) $(CFLAGS) $< -o $@ clean: - $(RM) $(EXECUTABLE) *.o + $(RM) *.o