ambed 1.3.0

Improved performances. Most device configuration can now run all
available channels concurrently. See readme for details.
This commit is contained in:
LX3JL 2017-11-13 08:42:32 +01:00
parent ddc52640df
commit 18a5cd9544
11 changed files with 182 additions and 96 deletions

View File

@ -48,6 +48,9 @@ public:
// destructor // destructor
virtual ~CAmbePacket(); virtual ~CAmbePacket();
// identity
bool IsAmbe(void) const { return true; }
// get // get
uint8 GetCodec(void) const { return m_uiCodec; } uint8 GetCodec(void) const { return m_uiCodec; }
uint8 *GetAmbe(void) { return m_uiAmbe; } uint8 *GetAmbe(void) { return m_uiAmbe; }

View File

@ -40,13 +40,17 @@ public:
// destructor // destructor
virtual ~CPacket() {}; virtual ~CPacket() {};
// identity
virtual bool IsVoice(void) const { return false; }
virtual bool IsAmbe(void) const { return false; }
// get // get
int GetChannel(void) const { return m_iCh; } int GetChannel(void) const { return m_iCh; }
uint8 GetPid(void) const { return m_uiPid; } uint8 GetPid(void) const { return m_uiPid; }
// set // set
void SetChannel(int i) { m_iCh = i; } void SetChannel(int i) { m_iCh = i; }
void SetPid(uint8 ui) { m_uiPid = ui; } void SetPid(uint8 ui) { m_uiPid = ui; }
protected: protected:
// data // data

View File

@ -70,6 +70,7 @@ protected:
bool OpenDevice(void); bool OpenDevice(void);
bool ResetDevice(void); bool ResetDevice(void);
bool ConfigureDevice(void); bool ConfigureDevice(void);
int GetDeviceFifoSize(void) const { return 2; }
// data // data
uint8 m_uiChCodecs[USB3003_NB_CH]; uint8 m_uiChCodecs[USB3003_NB_CH];

View File

@ -39,12 +39,12 @@
CUsb3xxxInterface::CUsb3xxxInterface(uint32 uiVid, uint32 uiPid, const char *szDeviceName, const char *szDeviceSerial) CUsb3xxxInterface::CUsb3xxxInterface(uint32 uiVid, uint32 uiPid, const char *szDeviceName, const char *szDeviceSerial)
{ {
m_FtdiHandle = NULL; m_FtdiHandle = NULL;
m_iDeviceFifoLevel = 0;
m_iActiveQueue = QUEUE_CHANNEL;
m_uiVid = uiVid; m_uiVid = uiVid;
m_uiPid = uiPid; m_uiPid = uiPid;
::strcpy(m_szDeviceName, szDeviceName); ::strcpy(m_szDeviceName, szDeviceName);
::strcpy(m_szDeviceSerial, szDeviceSerial); ::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() 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; 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 // base class
if ( ok ) if ( ok )
{ {
@ -118,11 +138,10 @@ void CUsb3xxxInterface::Task(void)
{ {
if ( IsValidSpeechPacket(Buffer, &iCh, &VoicePacket) ) if ( IsValidSpeechPacket(Buffer, &iCh, &VoicePacket) )
{ {
#ifdef DEBUG_DUMPFILE // update fifo level
g_AmbeServer.m_DebugFile << m_szDeviceName << "\t" << "->Sp" << iCh << std::endl; std::cout.flush(); // as we get a speech packet, it means that the device
#endif // channel fifo input decreased by 1
// update fifo status m_iChannelFifolLevel = MAX(0, m_iChannelFifolLevel-1);
m_iDeviceFifoLevel = MAX(m_iDeviceFifoLevel-1, 0);
// push back to relevant channel voice queue // push back to relevant channel voice queue
// our incoming channel packet has now been through the decoder // our incoming channel packet has now been through the decoder
@ -140,13 +159,14 @@ void CUsb3xxxInterface::Task(void)
} }
else if ( IsValidChannelPacket(Buffer, &iCh, &AmbePacket) ) else if ( IsValidChannelPacket(Buffer, &iCh, &AmbePacket) )
{ {
#ifdef DEBUG_DUMPFILE // update fifo level
g_AmbeServer.m_DebugFile << m_szDeviceName << "\t" << "->Ch" << iCh << std::endl; std::cout.flush(); // as we get a channel packet, it means that the device
#endif // speech fifo input decreased by 1
// update fifo status m_iSpeechFifolLevel = MAX(0, m_iSpeechFifolLevel-1);
m_iDeviceFifoLevel = MAX(m_iDeviceFifoLevel-1, 0);
// push back to relevant channel outcoming queue // push back to relevant channel outcoming queue
// we are done with this packet transcoding
// it's final step
Channel = GetChannelWithChannelOut(iCh); Channel = GetChannelWithChannelOut(iCh);
if ( Channel != NULL ) if ( Channel != NULL )
{ {
@ -178,9 +198,12 @@ void CUsb3xxxInterface::Task(void)
// get packet // get packet
CVoicePacket *Packet = (CVoicePacket *)Queue->front(); CVoicePacket *Packet = (CVoicePacket *)Queue->front();
Queue->pop(); Queue->pop();
// this is second step of transcoding
// we just received from hardware a decoded speech packet
// post it to relevant channel encoder // post it to relevant channel encoder
Packet->SetChannel(Channel->GetChannelOut()); int i = Channel->GetChannelOut();
m_SpeechQueue.push(Packet); Packet->SetChannel(i);
m_SpeechQueues[i]->push(Packet);
// done // done
done = false; done = false;
} }
@ -196,9 +219,12 @@ void CUsb3xxxInterface::Task(void)
// get packet // get packet
CAmbePacket *Packet = (CAmbePacket *)Queue->front(); CAmbePacket *Packet = (CAmbePacket *)Queue->front();
Queue->pop(); Queue->pop();
// this is first step of transcoding
// a fresh new packet to be transcoded is showing up
// post it to relevant channel decoder // post it to relevant channel decoder
Packet->SetChannel(Channel->GetChannelIn()); int i = Channel->GetChannelIn();
m_ChannelQueue.push(Packet); Packet->SetChannel(i);
m_ChannelQueues[i]->push(Packet);
// done // done
done = false; done = false;
} }
@ -207,57 +233,94 @@ void CUsb3xxxInterface::Task(void)
} }
} while (!done); } while (!done);
// process device incoming queues // process device incoming queues (aka to device)
// interlace speech and channels packets // interlace speech and channels packets
// and make sure that the fifo is always // and post to final device queue
// fed. do
unsigned long iQueueLevel = m_SpeechQueue.size() + m_ChannelQueue.size();
if ( ((m_iDeviceFifoLevel == 0) && (iQueueLevel >= 2)) || (m_iDeviceFifoLevel == 1) )
{ {
if ( m_iActiveQueue == QUEUE_CHANNEL ) done = true;
// loop on all channels
for ( int i = 0; i < GetNbChannels(); i++ )
{ {
// post next channel packet // speech
if ( !m_ChannelQueue.empty() ) if ( !m_SpeechQueues[i]->empty() )
{ {
// get packet // get packet
CAmbePacket *Packet = (CAmbePacket *)m_ChannelQueue.front(); CPacket *Packet = m_SpeechQueues[i]->front();
m_ChannelQueue.pop(); m_SpeechQueues[i]->pop();
//Post it // and push to device queue
EncodeChannelPacket(&Buffer, Packet->GetChannel(), Packet); m_DeviceQueue.push(Packet);
WriteBuffer(Buffer); // next
m_iDeviceFifoLevel++; done = false;
// and delete it }
#ifdef DEBUG_DUMPFILE // ambe
g_AmbeServer.m_DebugFile << m_szDeviceName << "\t" << "Ch" << Packet->GetChannel() << "->" << std::endl; std::cout.flush(); if ( !m_ChannelQueues[i]->empty() )
#endif {
delete Packet; // get packet
} CPacket *Packet = m_ChannelQueues[i]->front();
// and interlace m_ChannelQueues[i]->pop();
m_iActiveQueue = QUEUE_SPEECH; // and push to device queue
} m_DeviceQueue.push(Packet);
else // done = false;
{
// 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;
} }
// 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 // and wait a bit
CTimePoint::TaskSleepFor(2); CTimePoint::TaskSleepFor(2);

View File

@ -98,12 +98,13 @@ protected:
virtual void EncodeSpeechPacket(CBuffer *, int, CVoicePacket *) {} virtual void EncodeSpeechPacket(CBuffer *, int, CVoicePacket *) {}
// low level // low level
virtual bool OpenDevice(void) { return false; } virtual bool OpenDevice(void) { return false; }
virtual bool ResetDevice(void) { return false; } virtual bool ResetDevice(void) { return false; }
bool ReadDeviceVersion(void); bool ReadDeviceVersion(void);
bool DisableParity(void); bool DisableParity(void);
virtual bool ConfigureDevice(void) { return false; } virtual bool ConfigureDevice(void) { return false; }
bool ConfigureChannel(uint8, const uint8 *, int, int); bool ConfigureChannel(uint8, const uint8 *, int, int);
virtual int GetDeviceFifoSize(void) const { return 1; }
// io level // io level
bool ReadBuffer(CBuffer *); bool ReadBuffer(CBuffer *);
@ -117,17 +118,18 @@ protected:
protected: protected:
// data // data
uint32 m_uiVid; uint32 m_uiVid;
uint32 m_uiPid; uint32 m_uiPid;
char m_szDeviceName[FTDI_MAX_STRINGLENGTH]; char m_szDeviceName[FTDI_MAX_STRINGLENGTH];
char m_szDeviceSerial[FTDI_MAX_STRINGLENGTH]; char m_szDeviceSerial[FTDI_MAX_STRINGLENGTH];
FT_HANDLE m_FtdiHandle; FT_HANDLE m_FtdiHandle;
// queue // queue
CPacketQueue m_SpeechQueue; std::vector<CPacketQueue*> m_SpeechQueues;
CPacketQueue m_ChannelQueue; std::vector<CPacketQueue*> m_ChannelQueues;
int m_iDeviceFifoLevel; CPacketQueue m_DeviceQueue;
int m_iActiveQueue; int m_iSpeechFifolLevel;
int m_iChannelFifolLevel;
}; };
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////

View File

@ -47,7 +47,10 @@ public:
// destructor // destructor
virtual ~CVoicePacket(); virtual ~CVoicePacket();
// identity
bool IsVoice(void) const { return true; }
// get // get
uint8 *GetVoice(void) { return m_uiVoice; } uint8 *GetVoice(void) { return m_uiVoice; }
int GetVoiceSize(void) const { return m_iSize; } int GetVoiceSize(void) const { return m_iSize; }

View File

@ -48,8 +48,8 @@
// version ----------------------------------------------------- // version -----------------------------------------------------
#define VERSION_MAJOR 1 #define VERSION_MAJOR 1
#define VERSION_MINOR 2 #define VERSION_MINOR 3
#define VERSION_REVISION 1 #define VERSION_REVISION 0
// global ------------------------------------------------------ // global ------------------------------------------------------

View File

@ -22,6 +22,7 @@
// along with Foobar. If not, see <http://www.gnu.org/licenses/>. // along with Foobar. If not, see <http://www.gnu.org/licenses/>.
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
VERSION: 1.3.0
Hardware compatibility. Hardware compatibility.
====================== ======================
@ -37,13 +38,13 @@ This version of ambed is compatible with:
Available transcoding channels per device: Available transcoding channels per device:
device DMR->DSTAR DSTAR->DMR Nb Of concurrent channels device DMR->DSTAR DSTAR->DMR Nb Of concurrent channels
---------------------------------------------------------------------- -------------------------------------------------------------------------
3000(pair) 1 1 2 3000(pair) 1 1 2
3003 1 1 1 3003 1 1 2
3003(pair) 3 3 not tested 3003(pair) 3 3 4
3003-3000(pair) 2 2 not tested 3003-3000(pair) 2 2 not tested
3006 3 3 4 3006 3 3 6
3012 6 6 8 3012 6 6 12
Multiple devices can be used at the same time. Multiple devices can be used at the same time.
You need to use 3000 by pairs or paired with a 3003 You need to use 3000 by pairs or paired with a 3003

View File

@ -45,6 +45,7 @@ CCodecStream::CCodecStream(uint16 uiId, uint8 uiCodecIn, uint8 uiCodecOut)
m_bConnected = false; m_bConnected = false;
m_iAmbeSrcPtr = 0; m_iAmbeSrcPtr = 0;
m_iAmbeDestPtr = 0; m_iAmbeDestPtr = 0;
m_uiNbTotalPacketSent = 0;
m_uiNbPacketSent = 0; m_uiNbPacketSent = 0;
m_uiNbPacketReceived = 0; m_uiNbPacketReceived = 0;
m_uiNbPacketBad = 0; m_uiNbPacketBad = 0;
@ -120,6 +121,7 @@ bool CCodecStream::Init(uint16 uiPort)
m_pThread = new std::thread(CCodecStream::Thread, this); m_pThread = new std::thread(CCodecStream::Thread, this);
m_bConnected = true; m_bConnected = true;
m_FrameTimer.Now(); m_FrameTimer.Now();
m_uiNbTotalPacketSent = 0;
ResetStats(); ResetStats();
} }
else else
@ -181,11 +183,12 @@ void CCodecStream::Task(void)
// and increment pointer // and increment pointer
m_iAmbeSrcPtr = (m_iAmbeSrcPtr + 1) % m_AmbeSrc.size(); m_iAmbeSrcPtr = (m_iAmbeSrcPtr + 1) % m_AmbeSrc.size();
m_uiNbTotalPacketSent++;
m_uiNbPacketSent++; m_uiNbPacketSent++;
}*/ }*/
// any packt to send to trancoder ? // 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 ) if ( uiNbPacketToSend > 0 )
{ {
for ( int i = 0; i < uiNbPacketToSend; i++ ) for ( int i = 0; i < uiNbPacketToSend; i++ )
@ -196,6 +199,7 @@ void CCodecStream::Task(void)
// and increment pointer // and increment pointer
m_iAmbeSrcPtr = (m_iAmbeSrcPtr + 1) % m_AmbeSrc.size(); m_iAmbeSrcPtr = (m_iAmbeSrcPtr + 1) % m_AmbeSrc.size();
m_uiNbTotalPacketSent++;
m_uiNbPacketSent++; m_uiNbPacketSent++;
} }
} }
@ -283,15 +287,19 @@ void CCodecStream::ResetStats(void)
void CCodecStream::DisplayStats(void) void CCodecStream::DisplayStats(void)
{ {
//double fps = (double)m_uiNbPacketSent / m_StatsTimer.DurationSinceNow(); // get stats
double fps = (double)m_uiNbPacketReceived / m_StatsTimer.DurationSinceNow(); 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 << ") : "; // resets
std::cout << m_uiNbPacketSent << " / " << m_uiNbPacketReceived << " / " << m_uiNbPacketTimeout; ResetStats();
//std::cout << " / " << m_uiNbPacketBad;
std::cout << " ; " << fps << " fps";
std::cout << std::endl; // displays
char sz[256];
m_uiNbPacketBad = 0; 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;
} }

View File

@ -99,6 +99,7 @@ protected:
std::thread *m_pThread; std::thread *m_pThread;
CTimePoint m_TimeoutTimer; CTimePoint m_TimeoutTimer;
CTimePoint m_FrameTimer; CTimePoint m_FrameTimer;
uint32 m_uiNbTotalPacketSent;
// stats // stats
CTimePoint m_StatsTimer; CTimePoint m_StatsTimer;

View File

@ -8,10 +8,10 @@ EXECUTABLE=ambedtest
all: $(SOURCES) $(EXECUTABLE) all: $(SOURCES) $(EXECUTABLE)
$(EXECUTABLE): $(OBJECTS) $(EXECUTABLE): $(OBJECTS)
$(CC) $(LDFLAGS) $(OBJECTS) -Wl,-rpath,/usr/local/lib -o $@ $(CC) $(LDFLAGS) $(OBJECTS) -lftd2xx -Wl,-rpath,/usr/local/lib -o $@
.cpp.o: .cpp.o:
$(CC) $(CFLAGS) $< -o $@ $(CC) $(CFLAGS) $< -o $@
clean: clean:
$(RM) $(EXECUTABLE) *.o $(RM) *.o