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
virtual ~CAmbePacket();
// identity
bool IsAmbe(void) const { return true; }
// get
uint8 GetCodec(void) const { return m_uiCodec; }
uint8 *GetAmbe(void) { return m_uiAmbe; }

View File

@ -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

View File

@ -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];

View File

@ -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);

View File

@ -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<CPacketQueue*> m_SpeechQueues;
std::vector<CPacketQueue*> m_ChannelQueues;
CPacketQueue m_DeviceQueue;
int m_iSpeechFifolLevel;
int m_iChannelFifolLevel;
};
////////////////////////////////////////////////////////////////////////////////////////

View File

@ -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; }

View File

@ -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 ------------------------------------------------------

View File

@ -22,6 +22,7 @@
// along with Foobar. If not, see <http://www.gnu.org/licenses/>.
// ----------------------------------------------------------------------------
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

View File

@ -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;
}

View File

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

View File

@ -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