diff --git a/ambedtest/cambe.cpp b/ambedtest/cambe.cpp new file mode 100644 index 0000000..5809822 --- /dev/null +++ b/ambedtest/cambe.cpp @@ -0,0 +1,45 @@ +// +// cambe.cpp +// ambedtest +// +// Created by Jean-Luc Deltombe (LX3JL) on 16/05/2017. +// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved. +// +// ---------------------------------------------------------------------------- +// This file is part of xlxd. +// +// xlxd 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 3 of the License, or +// (at your option) any later version. +// +// xlxd 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 Foobar. If not, see . +// ---------------------------------------------------------------------------- + +#include "main.h" +#include +#include "cambe.h" + +//////////////////////////////////////////////////////////////////////////////////////// +// define + + +//////////////////////////////////////////////////////////////////////////////////////// +// constructor + +CAmbe::CAmbe() +{ + ::memset(m_uiAmbe, 0, sizeof(m_uiAmbe)); +} + +CAmbe::CAmbe(uint8 *ambe) +{ + ::memcpy(m_uiAmbe, ambe, sizeof(m_uiAmbe)); +} + diff --git a/ambedtest/cambe.h b/ambedtest/cambe.h new file mode 100644 index 0000000..404ac8c --- /dev/null +++ b/ambedtest/cambe.h @@ -0,0 +1,59 @@ +// +// cambe.h +// ambedtest +// +// Created by Jean-Luc Deltombe (LX3JL) on 16/05/2017. +// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved. +// +// ---------------------------------------------------------------------------- +// This file is part of xlxd. +// +// xlxd 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 3 of the License, or +// (at your option) any later version. +// +// xlxd 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 Foobar. If not, see . +// ---------------------------------------------------------------------------- + +#ifndef cambe_h +#define cambe_h + + +//////////////////////////////////////////////////////////////////////////////////////// +// define + +// frame sizes +#define AMBE_SIZE 9 + + +//////////////////////////////////////////////////////////////////////////////////////// +// class + +class CAmbe +{ +public: + // constructor + CAmbe(); + CAmbe(uint8 *); + + // destructor + virtual ~CAmbe() {} + + // get + const uint8 *GetData(void) const { return m_uiAmbe; } + +protected: + // data + uint8 m_uiAmbe[AMBE_SIZE]; +}; + + +//////////////////////////////////////////////////////////////////////////////////////// +#endif /* cambe_h */ diff --git a/ambedtest/cbuffer.cpp b/ambedtest/cbuffer.cpp new file mode 100644 index 0000000..d935939 --- /dev/null +++ b/ambedtest/cbuffer.cpp @@ -0,0 +1,200 @@ +// +// cbuffer.cpp +// xlxd +// +// Created by Jean-Luc Deltombe (LX3JL) on 02/11/2015. +// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved. +// +// ---------------------------------------------------------------------------- +// This file is part of xlxd. +// +// xlxd 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 3 of the License, or +// (at your option) any later version. +// +// xlxd 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 Foobar. If not, see . +// ---------------------------------------------------------------------------- + +#include "main.h" +#include +#include "cbuffer.h" + +//////////////////////////////////////////////////////////////////////////////////////// +// constructor + +CBuffer::CBuffer(uint8 *buffer, int len) +{ + resize(len); + ::memcpy(data(), buffer, len); +} + +//////////////////////////////////////////////////////////////////////////////////////// +// set + +void CBuffer::Set(uint8 *buffer, int len) +{ + resize(len); + ::memcpy(data(), buffer, len); +} + +void CBuffer::Set(const char *sz) +{ + resize(::strlen(sz)+1); + ::strcpy((char *)data(), sz); +} + +void CBuffer::Append(uint8 *buffer, int len) +{ + int n = (int)size(); + resize(n+len); + ::memcpy(&(data()[n]), buffer, len); +} + +void CBuffer::Append(uint8 ui, int len) +{ + int n = (int)size(); + resize(n+len); + ::memset(&(data()[n]), ui, len); +} + +void CBuffer::Append(uint8 ui) +{ + int n = (int)size(); + resize(n+sizeof(uint8)); + ::memcpy(&(data()[n]), &ui, sizeof(uint8)); +} + +void CBuffer::Append(uint16 ui) +{ + int n = (int)size(); + resize(n+sizeof(uint16)); + ::memcpy(&(data()[n]), &ui, sizeof(uint16)); +} + +void CBuffer::Append(uint32 ui) +{ + int n = (int)size(); + resize(n+sizeof(uint32)); + ::memcpy(&(data()[n]), &ui, sizeof(uint32)); +} + +void CBuffer::Append(const char *sz) +{ + Append((uint8 *)sz, (int)strlen(sz)); + Append((uint8)0x00); +} + +void CBuffer::ReplaceAt(int i, uint8 ui) +{ + if ( size() < (i+sizeof(uint8)) ) + { + resize(i+sizeof(uint8)); + } + *(uint8 *)(&(data()[i])) = ui; +} + +void CBuffer::ReplaceAt(int i, uint16 ui) +{ + if ( size() < (i+sizeof(uint16)) ) + { + resize(i+sizeof(uint16)); + } + *(uint16 *)(&(data()[i])) = ui; +} + +void CBuffer::ReplaceAt(int i, uint32 ui) +{ + if ( size() < (i+sizeof(uint32)) ) + { + resize(i+sizeof(uint32)); + } + *(uint32 *)(&(data()[i])) = ui; +} + +void CBuffer::ReplaceAt(int i, const uint8 *ptr, int len) +{ + if ( size() < (i+len) ) + { + resize(i+len); + } + ::memcpy(&(data()[i]), ptr, len); +} + +//////////////////////////////////////////////////////////////////////////////////////// +// operation + +int CBuffer::Compare(uint8 *buffer, int len) const +{ + int result = -1; + if ( size() >= len ) + { + result = ::memcmp(data(), buffer, len); + } + return result; +} + +int CBuffer::Compare(uint8 *buffer, int off, int len) const +{ + int result = -1; + if ( size() >= (off+len) ) + { + result = ::memcmp(&(data()[off]), buffer, len); + } + return result; +} + + +//////////////////////////////////////////////////////////////////////////////////////// +// operator + +bool CBuffer::operator ==(const CBuffer &Buffer) const +{ + if ( size() == Buffer.size() ) + { + return (::memcmp((const char *)data(), (const char *)Buffer.data(), size()) == 0); + } + return false; +} + +bool CBuffer::operator ==(const char *sz) const +{ + if ( size() == ::strlen(sz) ) + { + return (::memcmp((const char *)data(), sz, size()) == 0); + } + return false; +} + +CBuffer::operator const char *() const +{ + return (const char *)data(); +} + +//////////////////////////////////////////////////////////////////////////////////////// +// debug + +void CBuffer::DebugDump(std::ofstream &debugout) const +{ + for ( int i = 0; i < size(); i++ ) + { + char sz[16]; + sprintf(sz, "%02X", data()[i]); + debugout << sz; + if ( i == size()-1 ) + { + debugout << std::endl; + } + else + { + debugout << ','; + } + } +} + diff --git a/ambedtest/cbuffer.h b/ambedtest/cbuffer.h new file mode 100644 index 0000000..95bbae9 --- /dev/null +++ b/ambedtest/cbuffer.h @@ -0,0 +1,68 @@ +// +// cbuffer.h +// xlxd +// +// Created by Jean-Luc Deltombe (LX3JL) on 02/11/2015. +// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved. +// +// ---------------------------------------------------------------------------- +// This file is part of xlxd. +// +// xlxd 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 3 of the License, or +// (at your option) any later version. +// +// xlxd 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 Foobar. If not, see . +// ---------------------------------------------------------------------------- + +#ifndef cbuffer_h +#define cbuffer_h + +//////////////////////////////////////////////////////////////////////////////////////// + +class CBuffer : public std::vector +{ +public: + // constructor + CBuffer() {}; + CBuffer(uint8 *, int); + + // destructor + virtual ~CBuffer() {}; + + // set + void Set(uint8 *, int); + void Set(const char *); + void Append(uint8 *, int); + void Append(uint8, int); + void Append(uint8); + void Append(uint16); + void Append(uint32); + void Append(const char *); + void ReplaceAt(int, uint8); + void ReplaceAt(int, uint16); + void ReplaceAt(int, uint32); + void ReplaceAt(int, const uint8 *, int); + + // operation + int Compare(uint8 *, int) const; + int Compare(uint8 *, int, int) const; + + // operator + bool operator ==(const CBuffer &) const; + bool operator ==(const char *) const; + operator const char *() const; + + // debug + void DebugDump(std::ofstream &) const; +}; + +//////////////////////////////////////////////////////////////////////////////////////// +#endif /* cbuffer_h */ diff --git a/ambedtest/ccodecstream.cpp b/ambedtest/ccodecstream.cpp new file mode 100644 index 0000000..5910f8d --- /dev/null +++ b/ambedtest/ccodecstream.cpp @@ -0,0 +1,297 @@ +// +// ccodecstream.cpp +// xlxd +// +// Created by Jean-Luc Deltombe (LX3JL) on 13/04/2017. +// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved. +// +// ---------------------------------------------------------------------------- +// This file is part of xlxd. +// +// xlxd 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 3 of the License, or +// (at your option) any later version. +// +// xlxd 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 Foobar. If not, see . +// ---------------------------------------------------------------------------- + +#include "main.h" +#include +#include "ccodecstream.h" +#include "samples.h" +#include "ctranscoder.h" + +//////////////////////////////////////////////////////////////////////////////////////// +// define + +//////////////////////////////////////////////////////////////////////////////////////// +// constructor + +CCodecStream::CCodecStream(uint16 uiId, uint8 uiCodecIn, uint8 uiCodecOut) +{ + m_bStopThread = false; + m_pThread = NULL; + m_uiStreamId = uiId; + m_uiPid = 0; + m_uiCodecIn = uiCodecIn; + m_uiCodecOut = uiCodecOut; + m_bConnected = false; + m_iAmbeSrcPtr = 0; + m_iAmbeDestPtr = 0; + m_uiNbPacketSent = 0; + m_uiNbPacketReceived = 0; + m_uiNbPacketBad = 0; + m_uiNbPacketTimeout = 0; +} + +//////////////////////////////////////////////////////////////////////////////////////// +// destructor + +CCodecStream::~CCodecStream() +{ + // close socket + m_Socket.Close(); + + // kill threads + m_bStopThread = true; + if ( m_pThread != NULL ) + { + m_pThread->join(); + delete m_pThread; + } +} + +//////////////////////////////////////////////////////////////////////////////////////// +// initialization + +bool CCodecStream::Init(uint16 uiPort) +{ + bool ok; + + // reset stop flag + m_bStopThread = false; + + // copy our test data + if ( m_uiCodecIn == CODEC_AMBE2PLUS ) + { + // DMR -> DSTAR + for ( int i = 0; i < sizeof(g_uiDmrSample); i += AMBE_SIZE ) + { + CAmbe *ambe = new CAmbe(&(g_uiDmrSample[i])); + m_AmbeSrc.push_back(ambe); + } + for ( int i = 0; i < sizeof(g_uiDstarSample); i += AMBE_SIZE ) + { + CAmbe *ambe = new CAmbe(&(g_uiDstarSample[i])); + m_AmbeDest.push_back(ambe); + } + } + else + { + // DSTAR -> DMR + for ( int i = 0; i < sizeof(g_uiDstarSample); i += AMBE_SIZE ) + { + CAmbe *ambe = new CAmbe(&(g_uiDstarSample[i])); + m_AmbeSrc.push_back(ambe); + } + for ( int i = 0; i < sizeof(g_uiDmrSample); i += AMBE_SIZE ) + { + CAmbe *ambe = new CAmbe(&(g_uiDmrSample[i])); + m_AmbeDest.push_back(ambe); + } + } + + // create server's IP + m_Ip = g_Transcoder.GetAmbedIp(); + m_uiPort = uiPort; + + // create our socket + ok = m_Socket.Open(uiPort); + if ( ok ) + { + // start thread; + m_pThread = new std::thread(CCodecStream::Thread, this); + m_bConnected = true; + m_FrameTimer.Now(); + ResetStats(); + } + else + { + std::cout << "Error opening socket on port UDP" << uiPort << " on ip " << m_Ip << std::endl; + m_bConnected = false; + } + + // done + return ok; +} + +void CCodecStream::Close(void) +{ + // close socket + m_bConnected = false; + m_Socket.Close(); + + // kill threads + m_bStopThread = true; + if ( m_pThread != NULL ) + { + m_pThread->join(); + delete m_pThread; + m_pThread = NULL; + } +} + + +//////////////////////////////////////////////////////////////////////////////////////// +// thread + +void CCodecStream::Thread(CCodecStream *This) +{ + while ( !This->m_bStopThread ) + { + This->Task(); + } +} + +void CCodecStream::Task(void) +{ + CBuffer Buffer; + CIp Ip; + uint8 Ambe[AMBE_SIZE]; + + // connected ? + if ( m_bConnected ) + { + // time to send next packet to be transcoded ? + /*if ( m_FrameTimer.DurationSinceNow() >= 0.020 ) + { + // yes + m_FrameTimer.Now(); + + // encode packet @ send it + EncodeAmbePacket(&Buffer, m_AmbeSrc[m_iAmbeSrcPtr]->GetData()); + m_Socket.Send(Buffer, m_Ip, m_uiPort); + + // and increment pointer + m_iAmbeSrcPtr = (m_iAmbeSrcPtr + 1) % m_AmbeSrc.size(); + m_uiNbPacketSent++; + }*/ + + // any packt to send to trancoder ? + uint32 uiNbPacketToSend = (uint32)(m_FrameTimer.DurationSinceNow() * 50.0) - m_uiNbPacketSent; + if ( uiNbPacketToSend > 0 ) + { + for ( int i = 0; i < uiNbPacketToSend; i++ ) + { + // encode packet @ send it + EncodeAmbePacket(&Buffer, m_AmbeSrc[m_iAmbeSrcPtr]->GetData()); + m_Socket.Send(Buffer, m_Ip, m_uiPort); + + // and increment pointer + m_iAmbeSrcPtr = (m_iAmbeSrcPtr + 1) % m_AmbeSrc.size(); + m_uiNbPacketSent++; + } + } + + // any packet from transcoder + if ( m_Socket.Receive(&Buffer, &Ip, 1) != -1 ) + { + // crack + if ( IsValidAmbePacket(Buffer, Ambe) ) + { + m_TimeoutTimer.Now(); + + // check the PID + // check the transcoded packet + /*if ( ::memcmp(Ambe, m_AmbeDest[m_iAmbeDestPtr]->GetData(), AMBE_SIZE) != 0 ) + { + m_uiNbPacketBad++; + ::memcpy((void *)m_AmbeDest[m_iAmbeDestPtr]->GetData(), Ambe, AMBE_SIZE); + }*/ + + // and increment pointer + m_iAmbeDestPtr = (m_iAmbeDestPtr + 1) % m_AmbeDest.size(); + m_uiNbPacketReceived++; + + } + } + } + + // display stats + if ( m_DisplayStatsTimer.DurationSinceNow() >= 2.0 ) + { + m_DisplayStatsTimer.Now(); + DisplayStats(); + } + + // handle timeout + if ( m_TimeoutTimer.DurationSinceNow() >= (TRANSCODER_AMBEPACKET_TIMEOUT/1000.0f) ) + { + //std::cout << "ambed packet timeout" << std::endl; + m_uiNbPacketTimeout++; + } +} + +//////////////////////////////////////////////////////////////////////////////////////// +/// packet decoding helpers + +bool CCodecStream::IsValidAmbePacket(const CBuffer &Buffer, uint8 *Ambe) +{ + bool valid = false; + + if ( (Buffer.size() == 11) && (Buffer.data()[0] == m_uiCodecOut) ) + { + ::memcpy(Ambe, &(Buffer.data()[2]), 9); + valid = true; + } + return valid; +} + +//////////////////////////////////////////////////////////////////////////////////////// +/// packet encoding helpers + +void CCodecStream::EncodeAmbePacket(CBuffer *Buffer, const uint8 *Ambe) +{ + Buffer->clear(); + Buffer->Append(m_uiCodecIn); + Buffer->Append(m_uiPid); + Buffer->Append((uint8 *)Ambe, 9); +} + + +//////////////////////////////////////////////////////////////////////////////////////// +// stats helpers + +void CCodecStream::ResetStats(void) +{ + m_StatsTimer.Now(); + m_DisplayStatsTimer.Now(); + m_TimeoutTimer.Now(); + m_uiNbPacketSent = 0; + m_uiNbPacketReceived = 0; + m_uiNbPacketBad = 0; + m_uiNbPacketTimeout = 0; + +} + +void CCodecStream::DisplayStats(void) +{ + //double fps = (double)m_uiNbPacketSent / m_StatsTimer.DurationSinceNow(); + double fps = (double)m_uiNbPacketReceived / 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"; + + std::cout << std::endl; + + m_uiNbPacketBad = 0; +} diff --git a/ambedtest/ccodecstream.h b/ambedtest/ccodecstream.h new file mode 100644 index 0000000..568e466 --- /dev/null +++ b/ambedtest/ccodecstream.h @@ -0,0 +1,114 @@ +// +// ccodecstream.h +// xlxd +// +// Created by Jean-Luc Deltombe (LX3JL) on 13/04/2017. +// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved. +// +// ---------------------------------------------------------------------------- +// This file is part of xlxd. +// +// xlxd 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 3 of the License, or +// (at your option) any later version. +// +// xlxd 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 Foobar. If not, see . +// ---------------------------------------------------------------------------- + +#ifndef ccodecstream_h +#define ccodecstream_h + +#include "csemaphore.h" +#include "cudpsocket.h" +#include "ctimepoint.h" +#include "cambe.h" + + +//////////////////////////////////////////////////////////////////////////////////////// +// define + +// frame sizes +#define AMBE_SIZE 9 +#define AMBEPLUS_SIZE 9 + + +//////////////////////////////////////////////////////////////////////////////////////// +// class + +class CCodecStream +{ +public: + // constructor + CCodecStream(uint16, uint8, uint8); + + // destructor + virtual ~CCodecStream(); + + // initialization + bool Init(uint16); + void Close(void); + + // get + bool IsConnected(void) const { return m_bConnected; } + uint16 GetStreamId(void) const { return m_uiStreamId; } + + // task + static void Thread(CCodecStream *); + void Task(void); + + +protected: + // packet decoding helpers + bool IsValidAmbePacket(const CBuffer &, uint8 *); + + // packet encoding helpers + void EncodeAmbePacket(CBuffer *, const uint8 *); + + // stats helpers + void ResetStats(void); + void DisplayStats(void); + +protected: + // test data + std::vector m_AmbeSrc; + int m_iAmbeSrcPtr; + std::vector m_AmbeDest; + int m_iAmbeDestPtr; + + // data + uint16 m_uiStreamId; + uint16 m_uiPort; + uint8 m_uiPid; + uint8 m_uiCodecIn; + uint8 m_uiCodecOut; + + // socket + CIp m_Ip; + CUdpSocket m_Socket; + bool m_bConnected; + + // thread + bool m_bStopThread; + std::thread *m_pThread; + CTimePoint m_TimeoutTimer; + CTimePoint m_FrameTimer; + + // stats + CTimePoint m_StatsTimer; + CTimePoint m_DisplayStatsTimer; + uint32 m_uiNbPacketSent; + uint32 m_uiNbPacketReceived; + uint32 m_uiNbPacketBad; + uint32 m_uiNbPacketTimeout; +}; + + +//////////////////////////////////////////////////////////////////////////////////////// +#endif /* ccodecstream_h */ diff --git a/ambedtest/cip.cpp b/ambedtest/cip.cpp new file mode 100644 index 0000000..5cec9b5 --- /dev/null +++ b/ambedtest/cip.cpp @@ -0,0 +1,91 @@ +// +// cip.cpp +// xlxd +// +// Created by Jean-Luc Deltombe (LX3JL) on 31/10/2015. +// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved. +// +// ---------------------------------------------------------------------------- +// This file is part of xlxd. +// +// xlxd 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 3 of the License, or +// (at your option) any later version. +// +// xlxd 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 Foobar. If not, see . +// ---------------------------------------------------------------------------- + +#include "main.h" +#include +#include "cip.h" + +#include + +//////////////////////////////////////////////////////////////////////////////////////// +// constructors + +CIp::CIp() +{ + ::memset(&m_Addr, 0, sizeof(m_Addr)); + m_Addr.sin_family = AF_INET; +} + +CIp::CIp(const char *sz) +{ + ::memset(&m_Addr, 0, sizeof(m_Addr)); + m_Addr.sin_family = AF_INET; + // try xxx.xxx.xxx.xxxx first + m_Addr.sin_addr.s_addr = inet_addr(sz); + if ( m_Addr.sin_addr.s_addr == INADDR_NONE ) + { + // otherwise try to resolve via dns + hostent *record = gethostbyname(sz); + if( record != NULL ) + { + m_Addr.sin_addr.s_addr = ((in_addr * )record->h_addr)->s_addr; + } + } +} + +CIp::CIp(const struct sockaddr_in *sa) +{ + ::memcpy(&m_Addr, sa, sizeof(m_Addr)); +} + + +CIp::CIp(const CIp &ip) +{ + ::memcpy(&m_Addr, &ip.m_Addr, sizeof(m_Addr)); +} + +//////////////////////////////////////////////////////////////////////////////////////// +// set + +void CIp::SetSockAddr(struct sockaddr_in *sa) +{ + ::memcpy(&m_Addr, sa, sizeof(m_Addr)); +} + +//////////////////////////////////////////////////////////////////////////////////////// +// operator + +bool CIp::operator ==(const CIp &ip) const +{ + return ( (ip.m_Addr.sin_family == m_Addr.sin_family) && + (ip.m_Addr.sin_addr.s_addr == m_Addr.sin_addr.s_addr) && + (ip.m_Addr.sin_port == m_Addr.sin_port)) ; +} + +CIp::operator const char *() const +{ + return ::inet_ntoa(m_Addr.sin_addr); +} + + diff --git a/ambedtest/cip.h b/ambedtest/cip.h new file mode 100644 index 0000000..3a65fd6 --- /dev/null +++ b/ambedtest/cip.h @@ -0,0 +1,59 @@ +// +// cip.h +// xlxd +// +// Created by Jean-Luc Deltombe (LX3JL) on 31/10/2015. +// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved. +// +// ---------------------------------------------------------------------------- +// This file is part of xlxd. +// +// xlxd 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 3 of the License, or +// (at your option) any later version. +// +// xlxd 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 Foobar. If not, see . +// ---------------------------------------------------------------------------- + +#ifndef cip_h +#define cip_h + + +//////////////////////////////////////////////////////////////////////////////////////// +// class + +class CIp +{ +public: + // constructors + CIp(); + //CIp(uint8, uint8, uint8, uint8); + CIp(const struct sockaddr_in *); + CIp(const char *); + CIp(const CIp &); + + // destructor + virtual ~CIp() {}; + + // sockaddr + void SetSockAddr(struct sockaddr_in *); + struct sockaddr_in *GetSockAddr(void) { return &m_Addr; } + + // operator + bool operator ==(const CIp &) const; + operator const char *() const; + +protected: + // data + struct sockaddr_in m_Addr; +}; + +//////////////////////////////////////////////////////////////////////////////////////// +#endif /* cip_h */ diff --git a/ambedtest/csemaphore.cpp b/ambedtest/csemaphore.cpp new file mode 100644 index 0000000..3b91e82 --- /dev/null +++ b/ambedtest/csemaphore.cpp @@ -0,0 +1,72 @@ +// +// csemaphore.cpp +// xlxd +// +// Created by Jean-Luc Deltombe (LX3JL) on 16/04/2017. +// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved. +// +// ---------------------------------------------------------------------------- +// This file is part of xlxd. +// +// xlxd 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 3 of the License, or +// (at your option) any later version. +// +// xlxd 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 Foobar. If not, see . +// ---------------------------------------------------------------------------- + +#include "main.h" +#include "csemaphore.h" + +//////////////////////////////////////////////////////////////////////////////////////// +// constructor + +CSemaphore::CSemaphore() +{ + // Initialized as locked. + m_Count = 0; +} + +//////////////////////////////////////////////////////////////////////////////////////// +// operation + +void CSemaphore::Reset(void) +{ + std::unique_lock lock(m_Mutex); + m_Count = 0; +} + +void CSemaphore::Notify(void) +{ + std::unique_lock lock(m_Mutex); + m_Count++; + m_Condition.notify_one(); +} + +void CSemaphore::Wait(void) +{ + std::unique_lock lock(m_Mutex); + m_Condition.wait(lock, [&]{ return m_Count > 0; }); + m_Count--; +} + +bool CSemaphore::WaitFor(uint ms) +{ + std::chrono::milliseconds timespan(ms); + std::unique_lock lock(m_Mutex); + auto ok = m_Condition.wait_for(lock, timespan, [&]{ return m_Count > 0; }); + if ( ok ) + { + m_Count--; + } + return ok; + +} + diff --git a/ambedtest/csemaphore.h b/ambedtest/csemaphore.h new file mode 100644 index 0000000..0729512 --- /dev/null +++ b/ambedtest/csemaphore.h @@ -0,0 +1,56 @@ +// +// csemaphore.h +// xlxd +// +// Created by Jean-Luc Deltombe (LX3JL) on 16/04/2017. +// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved. +// +// ---------------------------------------------------------------------------- +// This file is part of xlxd. +// +// xlxd 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 3 of the License, or +// (at your option) any later version. +// +// xlxd 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 Foobar. If not, see . +// ---------------------------------------------------------------------------- + +#ifndef csemaphore_h +#define csemaphore_h + + +//////////////////////////////////////////////////////////////////////////////////////// +// class + +class CSemaphore +{ +public: + // constructor + CSemaphore(); + + // destructor + virtual ~CSemaphore() {}; + + // operation + void Reset(void); + void Notify(void); + void Wait(void); + bool WaitFor(uint); + +protected: + // data + std::mutex m_Mutex; + std::condition_variable m_Condition; + size_t m_Count; + +}; + +//////////////////////////////////////////////////////////////////////////////////////// +#endif /* csemaphore_h */ diff --git a/ambedtest/ctimepoint.cpp b/ambedtest/ctimepoint.cpp new file mode 100644 index 0000000..41b59f0 --- /dev/null +++ b/ambedtest/ctimepoint.cpp @@ -0,0 +1,53 @@ +// +// ctimepoint.cpp +// xlxd +// +// Created by Jean-Luc Deltombe (LX3JL) on 05/11/2015. +// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved. +// +// ---------------------------------------------------------------------------- +// This file is part of xlxd. +// +// xlxd 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 3 of the License, or +// (at your option) any later version. +// +// xlxd 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 Foobar. If not, see . +// ---------------------------------------------------------------------------- + +#include "main.h" +#include "ctimepoint.h" + +//////////////////////////////////////////////////////////////////////////////////////// +// constructor + +CTimePoint::CTimePoint() +{ + m_TimePoint = std::chrono::steady_clock::now(); +} + +//////////////////////////////////////////////////////////////////////////////////////// +// operation + +double CTimePoint::DurationSinceNow(void) const +{ + std::chrono::steady_clock::time_point Now = std::chrono::steady_clock::now(); + std::chrono::steady_clock::duration time_span = (Now - m_TimePoint); + return double(time_span.count()) * std::chrono::steady_clock::period::num / std::chrono::steady_clock::period::den; +} + +//////////////////////////////////////////////////////////////////////////////////////// +// task + +void CTimePoint::TaskSleepFor(uint ms) +{ + std::chrono::milliseconds timespan(ms); + std::this_thread::sleep_for(timespan); +} diff --git a/ambedtest/ctimepoint.h b/ambedtest/ctimepoint.h new file mode 100644 index 0000000..209e8c7 --- /dev/null +++ b/ambedtest/ctimepoint.h @@ -0,0 +1,55 @@ +// +// ctimepoint.h +// xlxd +// +// Created by Jean-Luc Deltombe (LX3JL) on 05/11/2015. +// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved. +// +// ---------------------------------------------------------------------------- +// This file is part of xlxd. +// +// xlxd 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 3 of the License, or +// (at your option) any later version. +// +// xlxd 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 Foobar. If not, see . +// ---------------------------------------------------------------------------- + +#ifndef ctimepoint_h +#define ctimepoint_h + + +//////////////////////////////////////////////////////////////////////////////////////// +// class + +class CTimePoint : public std::chrono::steady_clock::time_point +{ +public: + // constructor + CTimePoint(); + + // destructor + virtual ~CTimePoint() {} + + // operation + void Now(void) { m_TimePoint = std::chrono::steady_clock::now(); } + double DurationSinceNow(void) const; + + // task + static void TaskSleepFor(uint); + +protected: + // data + std::chrono::steady_clock::time_point m_TimePoint; +}; + + +//////////////////////////////////////////////////////////////////////////////////////// +#endif /* ctimepoint_h */ diff --git a/ambedtest/ctranscoder.cpp b/ambedtest/ctranscoder.cpp new file mode 100644 index 0000000..5d7805b --- /dev/null +++ b/ambedtest/ctranscoder.cpp @@ -0,0 +1,388 @@ +// +// ctranscoder.cpp +// xlxd +// +// Created by Jean-Luc Deltombe (LX3JL) on 13/04/2017. +// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved. +// +// ---------------------------------------------------------------------------- +// This file is part of xlxd. +// +// xlxd 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 3 of the License, or +// (at your option) any later version. +// +// xlxd 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 Foobar. If not, see . +// ---------------------------------------------------------------------------- + +#include "main.h" +#include "ctranscoder.h" + +//////////////////////////////////////////////////////////////////////////////////////// +// define + +// status +#define STATUS_IDLE 0 +#define STATUS_LOGGED 1 + +// timeout +#define AMBED_OPENSTREAM_TIMEOUT 200 // in ms + +//////////////////////////////////////////////////////////////////////////////////////// + +CTranscoder g_Transcoder; + + +//////////////////////////////////////////////////////////////////////////////////////// +// constructor + +CTranscoder::CTranscoder() +{ + m_bStopThread = false; + m_pThread = NULL; + m_Streams.reserve(12); + m_bConnected = false; + m_LastKeepaliveTime.Now(); + m_LastActivityTime.Now(); + m_bStreamOpened = false; + m_StreamidOpenStream = 0; + m_PortOpenStream = 0; +} + +//////////////////////////////////////////////////////////////////////////////////////// +// destructor + +CTranscoder::~CTranscoder() +{ + // close all streams + m_Mutex.lock(); + { + for ( int i = 0; i < m_Streams.size(); i++ ) + { + delete m_Streams[i]; + } + m_Streams.clear(); + + } + m_Mutex.unlock(); + + // kill threads + m_bStopThread = true; + if ( m_pThread != NULL ) + { + m_pThread->join(); + delete m_pThread; + } +} + +//////////////////////////////////////////////////////////////////////////////////////// +// initialization + +bool CTranscoder::Init(const CIp &ListenIp, const CIp &AmbedIp) +{ + bool ok; + + // reset stop flag + m_bStopThread = false; + + // create server's IP + m_ListenIp = ListenIp; + m_AmbedIp = AmbedIp; + + // create our socket + ok = m_Socket.Open(TRANSCODER_PORT); + if ( ok ) + { + // start thread; + m_pThread = new std::thread(CTranscoder::Thread, this); + } + else + { + std::cout << "Error opening socket on port UDP" << TRANSCODER_PORT << " on ip " << m_AmbedIp << std::endl; + } + + // done + return ok; +} + +void CTranscoder::Close(void) +{ + // close socket + m_Socket.Close(); + + // close all streams + m_Mutex.lock(); + { + for ( int i = 0; i < m_Streams.size(); i++ ) + { + delete m_Streams[i]; + } + m_Streams.clear(); + + } + m_Mutex.unlock(); + + // kill threads + m_bStopThread = true; + if ( m_pThread != NULL ) + { + m_pThread->join(); + delete m_pThread; + m_pThread = NULL; + } +} + +//////////////////////////////////////////////////////////////////////////////////////// +// thread + +void CTranscoder::Thread(CTranscoder *This) +{ + while ( !This->m_bStopThread ) + { + This->Task(); + } +} + +void CTranscoder::Task(void) +{ + CBuffer Buffer; + CIp Ip; + uint16 StreamId; + uint16 Port; + + // anything coming in from codec server ? + //if ( (m_Socket.Receive(&Buffer, &Ip, 20) != -1) && (Ip == m_Ip) ) + if ( m_Socket.Receive(&Buffer, &Ip, 20) != -1 ) + { + m_LastActivityTime.Now(); + + // crack packet + if ( IsValidStreamDescrPacket(Buffer, &StreamId, &Port) ) + { + //std::cout << "Transcoder stream " << (int) StreamId << " descr packet " << std::endl; + m_bStreamOpened = true; + m_StreamidOpenStream = StreamId; + m_PortOpenStream = Port; + m_SemaphoreOpenStream.Notify(); + } + else if ( IsValidNoStreamAvailablePacket(Buffer) ) + { + m_bStreamOpened = false; + m_SemaphoreOpenStream.Notify(); + } + else if ( IsValidKeepAlivePacket(Buffer) ) + { + if ( !m_bConnected ) + { + std::cout << "Transcoder connected at " << Ip << std::endl; + } + m_bConnected = true; + } + + } + + // handle end of streaming timeout + //CheckStreamsTimeout(); + + // handle queue from reflector + //HandleQueue(); + + // keep client alive + if ( m_LastKeepaliveTime.DurationSinceNow() > TRANSCODER_KEEPALIVE_PERIOD ) + { + // + HandleKeepalives(); + + // update time + m_LastKeepaliveTime.Now(); + } + } + +//////////////////////////////////////////////////////////////////////////////////////// +// manage streams + +CCodecStream *CTranscoder::GetStream(uint8 uiCodecIn) +{ + CBuffer Buffer; + + CCodecStream *stream = NULL; + + // do we need transcoding + if ( uiCodecIn != CODEC_NONE ) + { + // are we connected to server + if ( m_bConnected ) + { + // yes, post openstream request + EncodeOpenstreamPacket(&Buffer, uiCodecIn, (uiCodecIn == CODEC_AMBEPLUS) ? CODEC_AMBE2PLUS : CODEC_AMBEPLUS); + m_Socket.Send(Buffer, m_AmbedIp, TRANSCODER_PORT); + + // wait relpy here + if ( m_SemaphoreOpenStream.WaitFor(AMBED_OPENSTREAM_TIMEOUT) ) + { + if ( m_bStreamOpened ) + { + std::cout << "ambed openstream(" << m_StreamidOpenStream << ") ok" << std::endl; + + // create stream object + stream = new CCodecStream(m_StreamidOpenStream, uiCodecIn, (uiCodecIn == CODEC_AMBEPLUS) ? CODEC_AMBE2PLUS : CODEC_AMBEPLUS); + + // init it + if ( stream->Init(m_PortOpenStream) ) + { + // and append to list + Lock(); + m_Streams.push_back(stream); + Unlock(); + } + else + { + // send close packet + EncodeClosestreamPacket(&Buffer, stream->GetStreamId()); + m_Socket.Send(Buffer, m_AmbedIp, TRANSCODER_PORT); + // and delete + delete stream; + stream = NULL; + } + } + else + { + std::cout << "ambed openstream failed (no suitable channel available)" << std::endl; + } + } + else + { + std::cout << "ambed openstream timeout" << std::endl; + } + + } + } + return stream; +} + +void CTranscoder::ReleaseStream(CCodecStream *stream) +{ + CBuffer Buffer; + + if ( stream != NULL ) + { + // look for the stream + bool found = false; + Lock(); + { + for ( int i = 0; (i < m_Streams.size()) && !found; i++ ) + { + // compare object pointers + if ( (m_Streams[i]) == stream ) + { + // send close packet + EncodeClosestreamPacket(&Buffer, m_Streams[i]->GetStreamId()); + m_Socket.Send(Buffer, m_AmbedIp, TRANSCODER_PORT); + + // and close it + m_Streams[i]->Close(); + delete m_Streams[i]; + m_Streams.erase(m_Streams.begin()+i); + found = true; + } + } + } + Unlock(); + } +} + +//////////////////////////////////////////////////////////////////////////////////////// +// keepalive helpers + +void CTranscoder::HandleKeepalives(void) +{ + CBuffer keepalive; + + // send keepalive + EncodeKeepAlivePacket(&keepalive); + m_Socket.Send(keepalive, m_AmbedIp, TRANSCODER_PORT); + + // check if still with us + if ( m_bConnected && (m_LastActivityTime.DurationSinceNow() >= TRANSCODER_KEEPALIVE_TIMEOUT) ) + { + // no, disconnect + m_bConnected = false; + std::cout << "Transcoder keepalive timeout" << std::endl; + } +} + +//////////////////////////////////////////////////////////////////////////////////////// +// packet decoding helpers + +bool CTranscoder::IsValidKeepAlivePacket(const CBuffer &Buffer) +{ + uint8 tag[] = { 'A','M','B','E','D','P','O','N','G' }; + + bool valid = false; + if ( (Buffer.size() == 9) && (Buffer.Compare(tag, sizeof(tag)) == 0) ) + { + valid = true; + } + return valid; +} + +bool CTranscoder::IsValidStreamDescrPacket(const CBuffer &Buffer, uint16 *Id, uint16 *Port) +{ + uint8 tag[] = { 'A','M','B','E','D','S','T','D' }; + + bool valid = false; + if ( (Buffer.size() == 14) && (Buffer.Compare(tag, sizeof(tag)) == 0) ) + { + *Id = *(uint16 *)(&Buffer.data()[8]); + *Port = *(uint16 *)(&Buffer.data()[10]); + // uint8 CodecIn = Buffer.data()[12]; + // uint8 CodecOut = Buffer.data()[13]; + valid = true; + } + return valid; +} + +bool CTranscoder::IsValidNoStreamAvailablePacket(const CBuffer&Buffer) +{ + uint8 tag[] = { 'A','M','B','E','D','B','U','S','Y' }; + + return ( (Buffer.size() == 9) && (Buffer.Compare(tag, sizeof(tag)) == 0) ); +} + + +//////////////////////////////////////////////////////////////////////////////////////// +// packet encoding helpers + +void CTranscoder::EncodeKeepAlivePacket(CBuffer *Buffer) +{ + uint8 tag[] = { 'A','M','B','E','D','P','I','N','G' }; + + Buffer->Set(tag, sizeof(tag)); + Buffer->Append((uint8 *)(const char *)"XLX000 ", 8); +} + +void CTranscoder::EncodeOpenstreamPacket(CBuffer *Buffer, uint8 uiCodecIn, uint8 uiCodecOut) +{ + uint8 tag[] = { 'A','M','B','E','D','O','S' }; + + Buffer->Set(tag, sizeof(tag)); + Buffer->Append((uint8 *)(const char *)"XLX000 ", 8); + Buffer->Append((uint8)uiCodecIn); + Buffer->Append((uint8)uiCodecOut); +} + +void CTranscoder::EncodeClosestreamPacket(CBuffer *Buffer, uint16 uiStreamId) +{ + uint8 tag[] = { 'A','M','B','E','D','C','S' }; + + Buffer->Set(tag, sizeof(tag)); + Buffer->Append((uint16)uiStreamId); +} + diff --git a/ambedtest/ctranscoder.h b/ambedtest/ctranscoder.h new file mode 100644 index 0000000..2df670d --- /dev/null +++ b/ambedtest/ctranscoder.h @@ -0,0 +1,113 @@ +// +// ctranscoder.h +// xlxd +// +// Created by Jean-Luc Deltombe (LX3JL) on 13/04/2017. +// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved. +// +// ---------------------------------------------------------------------------- +// This file is part of xlxd. +// +// xlxd 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 3 of the License, or +// (at your option) any later version. +// +// xlxd 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 Foobar. If not, see . +// ---------------------------------------------------------------------------- + +#ifndef ctranscoder_h +#define ctranscoder_h + +#include "csemaphore.h" +#include "ccodecstream.h" +#include "cudpsocket.h" + +//////////////////////////////////////////////////////////////////////////////////////// +// define + + +//////////////////////////////////////////////////////////////////////////////////////// +// class + +class CTranscoder +{ +public: + // constructor + CTranscoder(); + + // destructor + virtual ~CTranscoder(); + + // initialization + bool Init(const CIp &, const CIp &); + void Close(void); + + // locks + void Lock(void) { m_Mutex.lock(); } + void Unlock(void) { m_Mutex.unlock(); } + + // get + const CIp &GetListenIp(void) const { return m_ListenIp; } + const CIp &GetAmbedIp(void) const { return m_AmbedIp; } + bool IsAmbedConnected(void) const { return m_bConnected; } + + // manage streams + CCodecStream *GetStream(uint8); + void ReleaseStream(CCodecStream *); + + // task + static void Thread(CTranscoder *); + void Task(void); + +protected: + // keepalive helpers + void HandleKeepalives(void); + + // packet decoding helpers + bool IsValidKeepAlivePacket(const CBuffer &); + bool IsValidStreamDescrPacket(const CBuffer &, uint16 *, uint16 *); + bool IsValidNoStreamAvailablePacket(const CBuffer&); + + // packet encoding helpers + void EncodeKeepAlivePacket(CBuffer *); + void EncodeOpenstreamPacket(CBuffer *, uint8, uint8); + void EncodeClosestreamPacket(CBuffer *, uint16); + +protected: + // IP's + CIp m_ListenIp; + CIp m_AmbedIp; + + // streams + std::mutex m_Mutex; + std::vector m_Streams; + + // sync objects for Openstream + CSemaphore m_SemaphoreOpenStream; + bool m_bStreamOpened; + uint16 m_StreamidOpenStream; + uint16 m_PortOpenStream; + + // thread + bool m_bStopThread; + std::thread *m_pThread; + + // socket + CUdpSocket m_Socket; + bool m_bConnected; + + // time + CTimePoint m_LastKeepaliveTime; + CTimePoint m_LastActivityTime; +}; + + +//////////////////////////////////////////////////////////////////////////////////////// +#endif /* ctranscoder_h */ diff --git a/ambedtest/cudpsocket.cpp b/ambedtest/cudpsocket.cpp new file mode 100644 index 0000000..e108614 --- /dev/null +++ b/ambedtest/cudpsocket.cpp @@ -0,0 +1,173 @@ +// +// cudpsocket.cpp +// xlxd +// +// Created by Jean-Luc Deltombe (LX3JL) on 31/10/2015. +// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved. +// +// ---------------------------------------------------------------------------- +// This file is part of xlxd. +// +// xlxd 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 3 of the License, or +// (at your option) any later version. +// +// xlxd 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 Foobar. If not, see . +// ---------------------------------------------------------------------------- + +#include "main.h" +#include +#include "cudpsocket.h" +#include "ctranscoder.h" + + +//////////////////////////////////////////////////////////////////////////////////////// +// constructor + +CUdpSocket::CUdpSocket() +{ + m_Socket = -1; +} + +//////////////////////////////////////////////////////////////////////////////////////// +// destructor + +CUdpSocket::~CUdpSocket() +{ + if ( m_Socket != -1 ) + { + Close(); + } +} + +//////////////////////////////////////////////////////////////////////////////////////// +// open & close + +bool CUdpSocket::Open(uint16 uiPort) +{ + bool open = false; + + // create socket + m_Socket = socket(PF_INET,SOCK_DGRAM,0); + if ( m_Socket != -1 ) + { + // initialize sockaddr struct + ::memset(&m_SocketAddr, 0, sizeof(struct sockaddr_in)); + m_SocketAddr.sin_family = AF_INET; + m_SocketAddr.sin_port = htons(uiPort); + m_SocketAddr.sin_addr.s_addr = inet_addr(g_Transcoder.GetListenIp()); + + if ( bind(m_Socket, (struct sockaddr *)&m_SocketAddr, sizeof(struct sockaddr_in)) == 0 ) + { + fcntl(m_Socket, F_SETFL, O_NONBLOCK); + open = true; + } + else + { + close(m_Socket); + m_Socket = -1; + } + } + + // done + return open; +} + +void CUdpSocket::Close(void) +{ + if ( m_Socket != -1 ) + { + close(m_Socket); + m_Socket = -1; + } +} + +//////////////////////////////////////////////////////////////////////////////////////// +// read + +int CUdpSocket::Receive(CBuffer *Buffer, CIp *Ip, int timeout) +{ + struct sockaddr_in Sin; + fd_set FdSet; + unsigned int uiFromLen = sizeof(struct sockaddr_in); + int iRecvLen = -1; + struct timeval tv; + + // socket valid ? + if ( m_Socket != -1 ) + { + // control socket + FD_ZERO(&FdSet); + FD_SET(m_Socket, &FdSet); + tv.tv_sec = timeout / 1000; + tv.tv_usec = (timeout % 1000) * 1000; + select(m_Socket + 1, &FdSet, 0, 0, &tv); + + // allocate buffer + Buffer->resize(UDP_BUFFER_LENMAX); + + // read + iRecvLen = (int)recvfrom(m_Socket, + (void *)Buffer->data(), UDP_BUFFER_LENMAX, + 0, (struct sockaddr *)&Sin, &uiFromLen); + + // handle + if ( iRecvLen != -1 ) + { + // adjust buffer size + Buffer->resize(iRecvLen); + + // get IP + Ip->SetSockAddr(&Sin); + } + } + + // done + return iRecvLen; +} + +//////////////////////////////////////////////////////////////////////////////////////// +// write + +int CUdpSocket::Send(const CBuffer &Buffer, const CIp &Ip) +{ + CIp temp(Ip); + return (int)::sendto(m_Socket, + (void *)Buffer.data(), Buffer.size(), + 0, (struct sockaddr *)temp.GetSockAddr(), sizeof(struct sockaddr_in)); +} + +int CUdpSocket::Send(const char *Buffer, const CIp &Ip) +{ + CIp temp(Ip); + return (int)::sendto(m_Socket, + (void *)Buffer, ::strlen(Buffer), + 0, (struct sockaddr *)temp.GetSockAddr(), sizeof(struct sockaddr_in)); +} + +int CUdpSocket::Send(const CBuffer &Buffer, const CIp &Ip, uint16 destport) +{ + CIp temp(Ip); + temp.GetSockAddr()->sin_port = htons(destport); + return (int)::sendto(m_Socket, + (void *)Buffer.data(), Buffer.size(), + 0, (struct sockaddr *)temp.GetSockAddr(), sizeof(struct sockaddr_in)); +} + +int CUdpSocket::Send(const char *Buffer, const CIp &Ip, uint16 destport) +{ + CIp temp(Ip); + temp.GetSockAddr()->sin_port = htons(destport); + return (int)::sendto(m_Socket, + (void *)Buffer, ::strlen(Buffer), + 0, (struct sockaddr *)temp.GetSockAddr(), sizeof(struct sockaddr_in)); +} + + diff --git a/ambedtest/cudpsocket.h b/ambedtest/cudpsocket.h new file mode 100644 index 0000000..e91ed80 --- /dev/null +++ b/ambedtest/cudpsocket.h @@ -0,0 +1,78 @@ +// +// cudpsocket.h +// xlxd +// +// Created by Jean-Luc Deltombe (LX3JL) on 31/10/2015. +// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved. +// +// ---------------------------------------------------------------------------- +// This file is part of xlxd. +// +// xlxd 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 3 of the License, or +// (at your option) any later version. +// +// xlxd 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 Foobar. If not, see . +// ---------------------------------------------------------------------------- + +#ifndef cudpsocket_h +#define cudpsocket_h + +#include +//#include +#include +#include +#include +#include +#include + +#include "cip.h" +#include "cbuffer.h" + +//////////////////////////////////////////////////////////////////////////////////////// +// define + +#define UDP_BUFFER_LENMAX 1024 + + +//////////////////////////////////////////////////////////////////////////////////////// +// class + +class CUdpSocket +{ +public: + // constructor + CUdpSocket(); + + // destructor + ~CUdpSocket(); + + // open & close + bool Open(uint16); + void Close(void); + int GetSocket(void) { return m_Socket; } + + // read + int Receive(CBuffer *, CIp *, int); + + // write + int Send(const CBuffer &, const CIp &); + int Send(const CBuffer &, const CIp &, uint16); + int Send(const char *, const CIp &); + int Send(const char *, const CIp &, uint16); + +protected: + // data + int m_Socket; + struct sockaddr_in m_SocketAddr; +}; + +//////////////////////////////////////////////////////////////////////////////////////// +#endif /* cudpsocket_h */ diff --git a/ambedtest/main.cpp b/ambedtest/main.cpp new file mode 100644 index 0000000..c0d975a --- /dev/null +++ b/ambedtest/main.cpp @@ -0,0 +1,77 @@ +// +// main.cpp +// ambedtest +// +// Created by Jean-Luc Deltombe (LX3JL) on 12/05/2017. +// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved. +// +// ---------------------------------------------------------------------------- +// This file is part of xlxd. +// +// xlxd 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 3 of the License, or +// (at your option) any later version. +// +// xlxd 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 Foobar. If not, see . +// ---------------------------------------------------------------------------- + +#include "main.h" +#include "ctranscoder.h" + +#define NB_STREAM 1 + +int main(int argc, const char * argv[]) +{ + std::vector Streams; + + // check args + if ( argc != 5 ) + { + std::cout << "Usage: ambedtest myip ambedip nbdmrstreams nbdstarstreams" << std::endl; + std::cout << "example: ambed 192.168.178.212 127.0.0.1 2 2" << std::endl; + return 1; + } + + // init the transcoder + std::cout << "Connecting to ambed server " << std::endl; + g_Transcoder.Init(CIp(argv[1]), CIp(argv[2])); + while ( !g_Transcoder.IsAmbedConnected() ); + std::cout << "Press enter to start test" << std::endl; + std::cin.get(); + + // create streams + int nDmr = atoi(argv[3]); + int nDstar = atoi(argv[4]); + + for ( int i = 0; i < nDmr; i++ ) + { + CTimePoint::TaskSleepFor(300); + Streams.push_back(g_Transcoder.GetStream(CODEC_AMBE2PLUS)); + } + + for ( int i = 0; i < nDstar; i++ ) + { + CTimePoint::TaskSleepFor(300); + Streams.push_back(g_Transcoder.GetStream(CODEC_AMBEPLUS)); + } + + // and loop wait + std::cin.get(); + + // close + for ( int i = 0; i < Streams.size(); i++ ) + { + g_Transcoder.ReleaseStream(Streams[i]); + } + g_Transcoder.Close(); + + // done + return 0; +} diff --git a/ambedtest/main.h b/ambedtest/main.h new file mode 100644 index 0000000..b6bc7ed --- /dev/null +++ b/ambedtest/main.h @@ -0,0 +1,103 @@ +// +// main.h +// ambedtest +// +// Created by Jean-Luc Deltombe (LX3JL) on 31/10/2015. +// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved. +// +// ---------------------------------------------------------------------------- +// This file is part of xlxd. +// +// xlxd 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 3 of the License, or +// (at your option) any later version. +// +// xlxd 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 Foobar. If not, see . +// ---------------------------------------------------------------------------- + +#ifndef main_h +#define main_h + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//////////////////////////////////////////////////////////////////////////////////////// +// defines + +// version ----------------------------------------------------- + +#define VERSION_MAJOR 1 +#define VERSION_MINOR 0 +#define VERSION_REVISION 0 + +// global ------------------------------------------------------ + + +// Transcoder server -------------------------------------------- + +#define TRANSCODER_PORT 10100 // UDP port +#define TRANSCODER_KEEPALIVE_PERIOD 5 // in seconds +#define TRANSCODER_KEEPALIVE_TIMEOUT 30 // in seconds +#define TRANSCODER_AMBEPACKET_TIMEOUT 400 // in ms + +// codec -------------------------------------------------------- + +#define CODEC_NONE 0 +#define CODEC_AMBEPLUS 1 // DStar +#define CODEC_AMBE2PLUS 2 // DMR + + + +// system constants --------------------------------------------- + + +//////////////////////////////////////////////////////////////////////////////////////// +// typedefs + +typedef unsigned char uint8; +typedef unsigned short uint16; +typedef unsigned int uint32; +typedef unsigned int uint; + + +//////////////////////////////////////////////////////////////////////////////////////// +// macros + +#define MIN(a,b) ((a) < (b))?(a):(b) +#define MAX(a,b) ((a) > (b))?(a):(b) +#define MAKEWORD(low, high) ((uint16)(((uint8)(low)) | (((uint16)((uint8)(high))) << 8))) +#define MAKEDWORD(low, high) ((uint32)(((uint16)(low)) | (((uint32)((uint16)(high))) << 16))) +#define LOBYTE(w) ((uint8)(uint16)(w & 0x00FF)) +#define HIBYTE(w) ((uint8)((((uint16)(w)) >> 8) & 0xFF)) +#define LOWORD(dw) ((uint16)(uint32)(dw & 0x0000FFFF)) +#define HIWORD(dw) ((uint16)((((uint32)(dw)) >> 16) & 0xFFFF)) + +//////////////////////////////////////////////////////////////////////////////////////// +// global objects + +class CTranscoder; +extern CTranscoder g_Transcoder; + +//////////////////////////////////////////////////////////////////////////////////////// +#endif /* main_h */ diff --git a/ambedtest/makefile b/ambedtest/makefile new file mode 100644 index 0000000..c85fe4c --- /dev/null +++ b/ambedtest/makefile @@ -0,0 +1,17 @@ +CC=g++ +CFLAGS=-c -std=c++11 -pthread +LDFLAGS=-std=c++11 -pthread +SOURCES=$(wildcard *.cpp) +OBJECTS=$(SOURCES:.cpp=.o) +EXECUTABLE=ambedtest + +all: $(SOURCES) $(EXECUTABLE) + +$(EXECUTABLE): $(OBJECTS) + $(CC) $(LDFLAGS) $(OBJECTS) -lftd2xx -Wl,-rpath,/usr/local/lib -o $@ + +.cpp.o: + $(CC) $(CFLAGS) $< -o $@ + +clean: + $(RM) *.o diff --git a/ambedtest/samples.h b/ambedtest/samples.h new file mode 100644 index 0000000..0cadefe --- /dev/null +++ b/ambedtest/samples.h @@ -0,0 +1,359 @@ +// +// dmrtodstarsample.h +// ambedtest +// +// Created by Jean-Luc Deltombe (LX3JL) on 16/05/2017. +// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved. +// +// ---------------------------------------------------------------------------- +// This file is part of xlxd. +// +// xlxd 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 3 of the License, or +// (at your option) any later version. +// +// xlxd 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 Foobar. If not, see . +// ---------------------------------------------------------------------------- + +#ifndef dmrtodstarsample_h +#define dmrtodstarsample_h + +uint8 g_uiDmrSample[] = +{ + 0xFD,0xAF,0xA2,0x32,0x0D,0x69,0x75,0xEF,0x64, + 0xDF,0x8F,0x80,0x10,0x2F,0x4D,0x61,0xEE,0x44, + 0xDF,0x8F,0x80,0x10,0x2F,0x4D,0x61,0xEF,0x20, + 0xFD,0x8D,0xA2,0x10,0x2C,0x6D,0x42,0x8F,0x44, + 0xBD,0xED,0xD7,0x74,0x2A,0x05,0x96,0x8F,0x88, + 0xBD,0xED,0xD7,0x74,0x2A,0x05,0xA5,0xAF,0x20, + 0xBD,0xED,0xD7,0x74,0x2A,0x04,0xA5,0xBE,0x88, + 0xFD,0x8D,0xA2,0x10,0x2C,0x6D,0x61,0xAE,0x44, + 0xBD,0xED,0xD7,0x74,0x2A,0x05,0xA5,0xAE,0x20, + 0xAD,0xED,0xC6,0x74,0x2A,0x05,0xA5,0xAE,0x88, + 0xBF,0xCD,0xA7,0x72,0x41,0xFF,0x30,0x23,0xA6, + 0x8C,0xFD,0x84,0x50,0x63,0xDB,0x16,0x02,0x20, + 0xFF,0x8F,0xC3,0x72,0x44,0xA1,0xD7,0x42,0x08, + 0xCA,0xB9,0xE7,0x54,0x44,0x69,0xF1,0x3C,0xD2, + 0xC8,0xB9,0xD6,0x54,0x64,0x08,0xC2,0x4A,0x20, + 0xC8,0xB9,0xC6,0x54,0x65,0x0A,0xF1,0x4A,0xE2, + 0x8A,0xF9,0x83,0x72,0x01,0x06,0x45,0x2A,0x6F, + 0x9B,0xE9,0x83,0x72,0x00,0x04,0x45,0x2B,0x20, + 0xB9,0xE9,0xA1,0x54,0x61,0x06,0x01,0x2B,0x6E, + 0xBB,0xE9,0x83,0x50,0x01,0x22,0x21,0x0B,0x6E, + 0xBB,0xE9,0x83,0x50,0x01,0x20,0x00,0x2B,0x20, + 0xBB,0xE9,0x93,0x50,0x00,0x22,0x01,0x2B,0x6E, + 0xB9,0xE9,0xA1,0x54,0x60,0x06,0x01,0x2B,0x6E, + 0x99,0xE9,0x83,0x74,0x41,0x37,0x00,0x2B,0x20, + 0x99,0xEB,0x83,0x52,0x45,0x57,0x15,0x2B,0x6A, + 0x99,0xEB,0x83,0x52,0x45,0x57,0x14,0x2B,0x6A, + 0x99,0xEA,0x83,0x52,0x45,0x57,0x14,0x29,0x20, + 0x99,0xEA,0x83,0x52,0x45,0x57,0x14,0x2B,0x7B, + 0xFB,0xAB,0xC4,0x76,0x42,0x0C,0xD1,0x2E,0xE2, + 0x91,0xD2,0xE2,0xE5,0x03,0x16,0x1A,0xD5,0x1C, + 0x6C,0x15,0xAD,0x96,0x64,0x55,0xC9,0xD3,0xA7, + 0xFD,0xAE,0xC0,0x30,0x66,0xD2,0xD1,0x76,0x09, + 0xD0,0x52,0xE5,0x16,0xEF,0xDF,0xA3,0x5F,0x20, + 0xE6,0x8E,0x2D,0xA8,0xEF,0x80,0x33,0x82,0x9B, + 0xD3,0xAA,0x1B,0xDC,0x8D,0x48,0x33,0x9E,0x72, + 0xA4,0x0A,0x00,0x21,0x8D,0x55,0xF8,0x22,0x20, + 0xA6,0x1A,0x23,0x64,0x9B,0x55,0xCB,0x13,0xF7, + 0xC2,0x36,0x20,0x77,0xEF,0x34,0xB4,0xB8,0x46, + 0x82,0x47,0x24,0x67,0xC7,0x90,0xE4,0x70,0x20, + 0x78,0xFA,0x0D,0x11,0x4A,0x44,0xE5,0x2B,0xAA, + 0x08,0xDF,0x2A,0x5E,0x34,0xF9,0x54,0x19,0x9F, + 0xDF,0x2E,0x2E,0xE9,0x78,0x38,0x09,0xEB,0x20, + 0xBC,0x7D,0x29,0xAB,0x72,0xA9,0x1A,0x05,0x55, + 0xC1,0xBE,0xE3,0x77,0x22,0xEC,0x0C,0xD3,0x90, + 0xC7,0xE3,0xA7,0x17,0x15,0xF0,0x81,0x3C,0x84, + 0xF4,0x40,0xC2,0x73,0x32,0xBB,0xBF,0x80,0x0F, + 0x4E,0xFF,0xA5,0x46,0x45,0x44,0xDB,0x7F,0x41, + 0x2C,0xAE,0xE0,0x61,0x60,0x28,0x0E,0x3B,0x1C, + 0xB7,0xC1,0x95,0xD4,0xA6,0x9F,0xE3,0xC1,0x01, + 0x26,0x61,0xFF,0x84,0x11,0xBC,0x81,0x0F,0x7B, + 0xD2,0x74,0xC8,0xD2,0x77,0xBB,0x6D,0x1B,0x20, + 0x95,0x49,0xC7,0x27,0x02,0x40,0xB7,0x00,0x10, + 0xE4,0xAB,0xE4,0x12,0x15,0x24,0x5D,0xFB,0x2F, + 0xF3,0x30,0xDC,0x32,0x11,0xDD,0x76,0x8D,0x24, + 0xE8,0x9A,0xE6,0x76,0x66,0x7B,0x85,0x0B,0xC1, + 0xEA,0xB8,0xC6,0x54,0x60,0x6B,0x85,0x0B,0xE3, + 0xEA,0xB8,0xC6,0x54,0x60,0x7B,0x85,0x09,0x20, + 0xE9,0xAA,0xC4,0x76,0x61,0x5D,0x94,0x09,0xE7, + 0xE9,0xAA,0xC4,0x76,0x61,0x5D,0x94,0x09,0xE7, + 0xBA,0x7C,0x88,0xD7,0xC0,0x97,0x65,0x08,0x20, + 0x92,0xB2,0x3E,0xCE,0xEC,0xF6,0x49,0x2A,0x69, + 0xB0,0xF7,0x61,0x04,0x80,0xB9,0xBC,0xC9,0x26, + 0x94,0xD0,0x44,0x40,0x96,0x22,0x8C,0xE0,0x20, + 0x96,0xB4,0x61,0xC2,0xB3,0x33,0xF1,0x44,0x10, + 0xA4,0x93,0x61,0xA0,0x39,0xDE,0xD8,0xA3,0xE7, + 0x96,0xB0,0x45,0x6E,0x3C,0x90,0x64,0x98,0x20, + 0x82,0xB6,0x06,0x87,0x30,0xFD,0x3D,0x01,0x46, + 0xE0,0xA1,0x49,0xD4,0x33,0x4E,0x75,0x65,0xB7, + 0xE6,0xB5,0x4F,0xD4,0x15,0xF1,0x20,0x4D,0x20, + 0xD4,0xB6,0x4C,0xF6,0x33,0xE5,0x10,0x19,0x1E, + 0xE4,0xD7,0x2C,0xDB,0x80,0x89,0x08,0xFF,0x00, + 0xC7,0xE5,0x4F,0xBD,0x8B,0x52,0xFD,0x25,0x20, + 0x83,0xE7,0x63,0x35,0x81,0xFA,0xBF,0x8E,0x23, + 0xE5,0x82,0x21,0x33,0x95,0x5A,0x5B,0x81,0x15, + 0xA1,0x8D,0x02,0x22,0xA3,0x5A,0x47,0x58,0x20, + 0xE2,0x8E,0x66,0x68,0x6D,0xF2,0x4F,0x74,0x0B, + 0x84,0xAF,0x12,0xCA,0x3A,0x50,0xF5,0x9F,0xE3, + 0xAB,0x6A,0xE6,0x46,0x55,0x38,0x09,0x91,0x1C, + 0xCC,0x56,0xE4,0x70,0x45,0x1E,0x73,0x39,0x2D, + 0xDB,0x61,0xA0,0x52,0x4E,0x79,0xA2,0xD9,0xDB, + 0x84,0x95,0xCE,0xE2,0x89,0xEB,0xCB,0x2E,0x1C, + 0x3F,0x2C,0xDA,0x82,0x7B,0x32,0x11,0xDD,0xF2, + 0xA6,0xA3,0xE0,0x00,0x67,0xE9,0x54,0x5A,0x71, + 0x9B,0x21,0xD4,0x16,0x49,0x76,0x40,0xF8,0x20, + 0xA5,0xB5,0x7A,0xBD,0xF4,0xC5,0x9D,0xBF,0xEB, + 0xA5,0xCE,0x40,0x86,0xAC,0x3E,0xC8,0x58,0xDD, + 0x90,0xAC,0x21,0x43,0xC1,0x5A,0x43,0x4F,0x1C, + 0xC0,0x9E,0x66,0x5A,0x4F,0x86,0x5D,0x71,0x0E, + 0x81,0x89,0x4E,0xF7,0x25,0xA4,0x08,0xF0,0xCF, + 0xBB,0x23,0x6C,0xCC,0x22,0x81,0xC1,0xE8,0x20, + 0x9F,0x4E,0xE0,0x03,0x36,0xD0,0x7A,0x89,0x37, + 0x88,0xA3,0xC0,0x27,0x66,0xE2,0xDD,0x9C,0xFF, + 0xB9,0x82,0xC2,0x45,0x04,0xE5,0xCF,0xDF,0x20, + 0xD2,0x34,0xE2,0xE6,0xBF,0x9D,0xAB,0xA9,0x88, + 0x97,0x6F,0x1D,0x98,0xAD,0xD2,0xDB,0x5A,0xD6, + 0xC1,0x4E,0x63,0x32,0x8B,0xD4,0x0B,0x5C,0x20, + 0xF0,0x7C,0x40,0x07,0xBD,0x97,0x5C,0x2C,0x95, + 0x94,0x38,0x03,0x04,0xDF,0x74,0x98,0x63,0xF7, + 0xB4,0x1A,0x41,0x04,0x86,0xFD,0x4C,0xBD,0x84, + 0x80,0x65,0x27,0x15,0xF5,0xB1,0x94,0x31,0xF7, + 0xA4,0x43,0x22,0x17,0xD0,0x7B,0xC3,0x59,0x5F, + 0xC6,0x4C,0x45,0x06,0x05,0xB0,0x31,0xA3,0x20, + 0xF2,0x2C,0xA6,0x32,0x51,0xE2,0x41,0x48,0x26, + 0xA3,0x4E,0x1A,0xAC,0x35,0x94,0xA1,0xF5,0xDF, + 0x92,0x19,0x0F,0x4C,0x65,0xB0,0x9D,0x55,0x20, + 0x6F,0xD6,0xDE,0x53,0xCF,0xA2,0xF3,0x2F,0x6D, + 0x8F,0x21,0x8B,0x4A,0xCF,0x6D,0x90,0x61,0xDE, + 0xB8,0x00,0x5F,0xCA,0x41,0xF4,0xD5,0xDD,0x84, + 0xF8,0x50,0x4A,0x8A,0x6F,0x54,0x90,0x42,0xD8, + 0x14,0xED,0xA6,0x1D,0x3D,0x5F,0x90,0x85,0x51, + 0xB4,0xB2,0xC2,0x35,0x55,0xAD,0x21,0x69,0x24, + 0xAF,0x86,0xC4,0x31,0x35,0x3C,0xD9,0x84,0x73, + 0x8F,0xB6,0xC6,0x33,0x75,0x19,0x9A,0xC0,0x02, + 0x9C,0xA6,0xD5,0x53,0x55,0x7A,0xDC,0x87,0x20, + 0xF9,0xA9,0xE7,0x70,0x64,0x59,0xA5,0x6B,0xF4, + 0xF9,0xAB,0xE7,0x56,0x60,0x29,0x93,0x59,0xE6, + 0xE9,0xA9,0xE7,0x70,0x64,0x4B,0xA4,0x68,0x1C, + 0xCD,0x9D,0xE2,0x52,0x42,0xA3,0xA0,0x26,0x2C, + 0xD0,0x25,0x82,0x93,0xB4,0x33,0x2F,0x73,0xF3, + 0x65,0x1C,0xDD,0x05,0x73,0x26,0xB1,0x09,0x84, + 0x80,0x95,0xC7,0x67,0x35,0x43,0x14,0x05,0x9D, + 0xBF,0xEE,0x94,0x52,0x21,0xC9,0x34,0x24,0x92, + 0xDD,0x8C,0xC1,0x52,0x00,0xA7,0xC3,0x56,0x20, + 0xDD,0x8C,0xC1,0x52,0x00,0xB5,0xE0,0x76,0x7F, + 0xFD,0x8C,0xC2,0x50,0x02,0xD6,0xE5,0x74,0x5B, + 0xFD,0x8C,0xC2,0x50,0x02,0xD4,0xE4,0x76,0x20, + 0xDD,0xAC,0xE2,0x52,0x06,0x92,0xD3,0x74,0x5B, + 0xCC,0xBC,0xE2,0x52,0x06,0x92,0xD3,0x77,0x59, + 0xCC,0xBC,0xE3,0x52,0x07,0x92,0xE0,0x77,0x20, + 0xAC,0xAA,0x40,0x20,0x00,0x44,0x40,0x80,0x80, + 0xC6,0xBE,0x1C,0xBA,0xFD,0xB0,0x31,0xB5,0x9B, + 0xC4,0xBE,0x27,0xB1,0xCB,0x74,0x6B,0x1F,0x04, + 0xCC,0x24,0x43,0x23,0xC5,0xD4,0xAB,0x96,0xB7, + 0xDA,0x30,0x64,0x56,0x80,0x4F,0x9F,0xDD,0x0A, + 0xBB,0x10,0x02,0x1F,0x4C,0xB0,0xF1,0xF4,0x20, + 0xFA,0x05,0x0F,0x59,0x55,0xFC,0x5F,0x5A,0x5F, + 0xAF,0x85,0xA6,0x41,0x28,0xA7,0x48,0x0C,0x09, + 0xF8,0xF2,0xA5,0x15,0x13,0xAC,0x5D,0xBE,0x20, + 0xEB,0xF0,0xA6,0x11,0x55,0xC9,0x7B,0xD9,0x12, + 0x9A,0x82,0x82,0x17,0x78,0x09,0x3D,0x00,0xE2, + 0xFD,0x2C,0x3C,0x89,0x5C,0x6E,0x09,0xCB,0x20, + 0x9E,0x6D,0x29,0xE9,0x13,0xDA,0x1E,0x73,0x71, + 0xAE,0x6C,0xC1,0x63,0x50,0xA1,0x5D,0xDF,0x33, + 0xC6,0xBA,0xE7,0x23,0x02,0x02,0x49,0x8A,0x20, + 0xB1,0x85,0xC7,0x57,0x41,0x10,0x41,0x50,0xE9, + 0x5D,0xD5,0xEC,0x53,0xAA,0xD2,0xB3,0x3F,0x7F, + 0x9A,0x5A,0xA5,0x66,0x59,0xA1,0x8E,0x7B,0x20, + 0xFA,0x28,0x78,0xBA,0x27,0x7D,0xCD,0x59,0x06, + 0x8D,0x15,0x4A,0xDF,0x05,0x19,0xF1,0x86,0x95, + 0x91,0x96,0xE7,0x55,0x24,0x06,0x55,0x04,0x1C, + 0x85,0x4B,0x34,0xD2,0x06,0xB9,0xDA,0x37,0xFF, + 0xF5,0x2B,0x62,0xD0,0x05,0xD3,0x5F,0x36,0x21, + 0xF6,0x3A,0x42,0xC1,0x33,0xD5,0x4A,0x44,0x20, + 0xD2,0x0F,0x66,0xE1,0x03,0x3B,0x5C,0x4D,0xAA, + 0xE6,0x6F,0x4B,0xA0,0x43,0x19,0xD1,0x55,0x7E, + 0xE6,0x7D,0x5A,0xE4,0x67,0x7E,0xF5,0x56,0x20, + 0xB9,0xE8,0x81,0x52,0x61,0x73,0x00,0x2A,0x6B, + 0xB9,0xE8,0x81,0x52,0x61,0x73,0x00,0x2A,0x6B, + 0xB9,0xE8,0x81,0x52,0x61,0x73,0x00,0x2A,0x20, + 0xB9,0xE8,0x81,0x52,0x61,0x73,0x00,0x2A,0x6B, + 0xB9,0xE8,0x81,0x52,0x61,0x73,0x00,0x2A,0x6B, +}; + +uint8 g_uiDstarSample[] = +{ + 0x67,0xE4,0x04,0x42,0x22,0x0F,0xE5,0x95,0xB6, + 0x5E,0x84,0x1E,0x52,0xC6,0x0D,0x1C,0xD6,0x08, + 0x6A,0xC5,0x12,0x5A,0x85,0x89,0x10,0x56,0x02, + 0x72,0xA7,0x16,0x62,0x84,0x03,0x04,0xF6,0x0E, + 0x1E,0x26,0x1A,0x03,0x43,0x8D,0x68,0xE3,0xB4, + 0x6E,0xA4,0x9A,0x5A,0xE4,0x0A,0x18,0x74,0x0E, + 0x02,0xA4,0x14,0x3B,0x03,0x0E,0x40,0xB1,0x32, + 0x6A,0xE6,0x90,0x62,0xC5,0x8D,0x20,0x94,0x46, + 0x62,0xC5,0x12,0x7A,0x66,0x08,0x18,0x06,0x8C, + 0x2E,0xC5,0x12,0x23,0x62,0x02,0x54,0xA1,0xBC, + 0x7A,0xC4,0x12,0x7A,0x84,0x00,0x08,0xD7,0x42, + 0x6A,0x84,0x12,0x42,0xC7,0x89,0x00,0x26,0xC4, + 0x1A,0xC4,0x14,0x23,0xA3,0x85,0x4C,0x20,0x7A, + 0x0E,0x27,0x90,0x03,0x22,0x09,0x48,0xC2,0xF4, + 0x3A,0x66,0x92,0x2B,0x21,0x8E,0x6C,0x73,0xF0, + 0x6A,0xE5,0x14,0x72,0x66,0x04,0x00,0x97,0x42, + 0x1E,0x47,0x90,0x3B,0x23,0x80,0x70,0x81,0xBC, + 0x6E,0x86,0x18,0x52,0xC4,0x85,0x24,0x26,0x84, + 0x46,0xE7,0x16,0x6A,0xE5,0x05,0x0C,0xB6,0xC8, + 0xAC,0x47,0xBC,0x00,0x45,0x06,0x54,0x27,0x6E, + 0xC8,0xA7,0x3A,0x79,0x61,0x80,0x0C,0xC2,0x5A, + 0x76,0xA7,0x1E,0x5A,0x84,0x04,0x20,0xB5,0x0E, + 0xC8,0x05,0xBC,0x49,0x01,0x83,0x10,0x41,0x56, + 0xB0,0x26,0x30,0x20,0xE6,0x00,0x40,0x06,0xAE, + 0x66,0xA7,0x1E,0x4A,0x87,0x05,0x0C,0x26,0x0C, + 0xD1,0x29,0xAE,0x11,0x02,0x00,0x38,0x05,0x66, + 0x1E,0xC4,0x12,0x33,0x03,0x05,0x78,0x23,0x72, + 0x7A,0x47,0x18,0x5A,0x46,0x8C,0x38,0x06,0xC6, + 0xB8,0x05,0xB4,0x28,0x05,0x02,0x74,0xF6,0xE8, + 0x02,0xE4,0x12,0x23,0xE0,0x80,0x60,0xF1,0x36, + 0x12,0x64,0x1C,0x13,0x22,0x0A,0x74,0x32,0xB2, + 0x2E,0xE6,0x94,0x1B,0x22,0x0B,0x74,0xF2,0xF4, + 0x5E,0xC7,0x9C,0x5A,0xC4,0x89,0x2C,0x17,0xC4, + 0x9D,0xE6,0xBC,0xA9,0x85,0xA0,0xFD,0xCD,0xB2, + 0x8E,0x56,0x02,0x69,0x7F,0x8A,0xF7,0x6A,0x0B, + 0xE0,0x6B,0x9E,0x13,0xC8,0xFE,0x22,0x45,0xAD, + 0xA9,0x00,0x8C,0xAA,0xBD,0x78,0x03,0xBB,0x90, + 0xA8,0xB7,0x7F,0xE6,0xF9,0xA6,0x32,0x28,0xD9, + 0xF1,0x55,0xFD,0xF5,0xFB,0xAA,0x6B,0x51,0xFA, + 0xBC,0xF1,0xF1,0x46,0x8A,0x6F,0x7B,0xB7,0x2A, + 0xED,0x34,0x4D,0xF6,0x4D,0xAC,0x28,0xCF,0xC9, + 0xA0,0x74,0xC6,0xB0,0x4F,0x83,0x1E,0x39,0xE6, + 0x9C,0xD4,0x92,0xA1,0x15,0xBC,0xA2,0xB7,0xA1, + 0xEB,0x90,0x18,0xE0,0x55,0x23,0x96,0x45,0xC3, + 0xD3,0x10,0xB0,0x92,0x13,0xF4,0xC8,0x52,0x8A, + 0xD0,0x4B,0x8C,0x63,0x00,0x28,0xF1,0x66,0x27, + 0x5A,0xA6,0x12,0x03,0x47,0x66,0x7B,0x89,0x42, + 0x5F,0xC3,0x90,0x1A,0x35,0xC6,0xB3,0x8F,0x62, + 0x52,0xC7,0x92,0x4A,0xF7,0x47,0x2C,0xD4,0x42, + 0x3B,0xE2,0x8C,0x2A,0x40,0x12,0xC2,0x62,0xA4, + 0x6B,0xA2,0x1C,0x43,0xE6,0xEA,0xE0,0xC3,0x2A, + 0xEA,0x27,0x14,0x9B,0xA5,0xB2,0xD0,0xE9,0xB6, + 0x4F,0x82,0x90,0x3A,0xE5,0x87,0xBF,0x9E,0xE6, + 0xBE,0x0F,0x92,0xF2,0x41,0x47,0x75,0x37,0x64, + 0x56,0x45,0x12,0x52,0x64,0x0A,0x20,0xA6,0xCE, + 0xA8,0xC9,0x04,0xF9,0x22,0x8A,0x29,0x46,0x97, + 0x3A,0x07,0x02,0x52,0x01,0x19,0x75,0xC8,0x4A, + 0x12,0x47,0x14,0x13,0x62,0x88,0x60,0x83,0xF6, + 0xBD,0xEB,0xA0,0x70,0x26,0x89,0x50,0x23,0x94, + 0x76,0x45,0x90,0x6A,0x46,0x04,0x2C,0x37,0x8C, + 0xE8,0xC2,0x18,0x9B,0xC4,0x9F,0x1B,0xAA,0xA6, + 0x89,0xAC,0x58,0xE1,0xE8,0x97,0x4D,0x9D,0xBF, + 0xCC,0x7A,0x45,0x9D,0xEF,0x8B,0x8F,0x49,0x1E, + 0xF8,0x19,0x41,0x95,0xAD,0xC9,0x8B,0x88,0x99, + 0xFC,0xDF,0x43,0xA4,0x8B,0xD7,0xE0,0x5A,0xB5, + 0x8C,0xBC,0xCD,0xF1,0x8F,0x5E,0xB8,0xFC,0x85, + 0xDD,0x5A,0x5D,0x99,0xD8,0x4E,0x4A,0x2A,0xA9, + 0x88,0x1E,0x4D,0xD6,0x9C,0x8A,0x61,0xDB,0x96, + 0xB9,0x38,0xED,0x29,0x36,0xE0,0x37,0xFD,0xD8, + 0x9C,0xBF,0x2C,0x20,0x67,0x8C,0xF3,0x58,0xB1, + 0xF8,0xBB,0x20,0x78,0xA5,0xD8,0xF0,0xBF,0x21, + 0xF5,0x18,0xB2,0x09,0x91,0xFA,0x6E,0x02,0x51, + 0xC8,0x7A,0x2A,0x79,0xFE,0x1D,0x22,0xA4,0x17, + 0xD1,0x9A,0x65,0x20,0x7B,0x81,0xF2,0x5C,0x51, + 0xE8,0x79,0x79,0x2F,0x3C,0x54,0xF2,0xBB,0x7A, + 0xE1,0xDF,0x6D,0x9C,0x3A,0x01,0x93,0xF1,0xE4, + 0xB9,0x98,0x79,0xBD,0x5A,0xC4,0x81,0xCE,0x09, + 0x98,0x5E,0xE9,0xA4,0x2A,0xD5,0x3B,0x3D,0x97, + 0xD5,0x38,0xFF,0x87,0xD7,0xBE,0x99,0xFB,0x90, + 0x17,0xE3,0x9C,0x53,0x02,0x0B,0xFB,0x1A,0x5E, + 0x23,0xA3,0x0A,0x32,0x41,0x14,0xFA,0xE3,0xAE, + 0xF8,0xEB,0xAA,0x71,0x4E,0x1B,0x0E,0xA4,0xD1, + 0x5E,0x85,0x90,0x4B,0xAE,0x86,0xDE,0x1F,0xF2, + 0x7B,0xE1,0x04,0x5A,0x0D,0x1B,0x7C,0x9C,0xE2, + 0x6F,0xA5,0x12,0x62,0x02,0xF1,0xA3,0xC2,0x00, + 0x6B,0x66,0x06,0x3B,0x90,0x28,0xB6,0x8A,0x32, + 0xF9,0x19,0xFD,0xC8,0xCF,0x00,0xC5,0xA9,0x74, + 0xC1,0x1C,0x73,0xC9,0x68,0xD4,0x82,0x5A,0x9B, + 0xB4,0xDF,0xE7,0x87,0x4A,0x8B,0xEE,0xE9,0x8C, + 0x9B,0x53,0xD1,0x4C,0x7D,0xDC,0x45,0xEA,0x9F, + 0x93,0x57,0x0C,0x5B,0xA0,0x61,0x7F,0xD1,0x61, + 0xE3,0x75,0x1C,0xB0,0x23,0x12,0xAA,0x1B,0xE9, + 0x6B,0xC4,0x9C,0x0B,0x42,0x98,0xE4,0x7F,0x8A, + 0x62,0xE2,0x86,0x32,0x92,0x42,0x4E,0x4C,0x92, + 0x43,0xA4,0x94,0x72,0x42,0xB2,0x9B,0x03,0xCE, + 0xC3,0x42,0x2A,0x11,0xBE,0x82,0xAF,0x47,0x8A, + 0x90,0xFE,0x45,0x3D,0x49,0x2C,0xD5,0x2F,0xD2, + 0xA8,0x5D,0x4D,0x3D,0x38,0xE9,0xC1,0x2F,0x9E, + 0xB1,0x52,0x63,0xF7,0x99,0xFC,0x98,0x69,0x09, + 0xC8,0x51,0xFB,0xA5,0x0A,0xEA,0xDC,0x8A,0x9D, + 0xF9,0x16,0x6D,0x9C,0xEB,0xF8,0x4E,0x4A,0x86, + 0xCC,0x57,0xE9,0x67,0x3B,0xA0,0x6D,0x2B,0x8F, + 0x81,0xF1,0x6F,0x0F,0xDE,0xC9,0xD1,0x9A,0xDB, + 0xA0,0x56,0xED,0xBE,0xD0,0xB9,0xED,0xCB,0x92, + 0x9C,0x55,0xB8,0xD8,0x21,0xFA,0x0D,0xC5,0xF2, + 0xC4,0xF3,0xEE,0x3A,0x07,0x57,0xAF,0x0F,0x13, + 0x2F,0x22,0x12,0x3A,0x33,0x68,0xA0,0x46,0x10, + 0x8D,0xA0,0x2A,0x1B,0x9C,0x05,0xD1,0x6B,0x10, + 0x1E,0x84,0x0A,0x5B,0xC8,0x5F,0xAB,0x82,0xBE, + 0xEA,0x03,0x32,0x69,0x32,0xE2,0xEB,0x33,0xC3, + 0x2F,0xA6,0x1A,0x13,0xE5,0xFE,0xDB,0x24,0xFE, + 0x73,0xE3,0x1C,0x63,0x16,0xEA,0xEC,0xE2,0xEE, + 0x6A,0xC4,0x12,0x33,0x95,0x26,0x57,0x28,0x82, + 0xB9,0x24,0x78,0x51,0xE1,0x15,0xB0,0xCF,0xE1, + 0xE0,0x85,0x32,0x61,0x23,0x0E,0x00,0x91,0x90, + 0x5A,0x46,0x12,0x72,0xA4,0x80,0x38,0xF6,0xCE, + 0xBD,0x8B,0x04,0x9B,0x84,0x07,0x24,0xBB,0x48, + 0x6E,0x25,0x18,0x52,0xC4,0x02,0x24,0xB4,0x8A, + 0x92,0x42,0x14,0x91,0x45,0x18,0x71,0x94,0xB4, + 0xD9,0x6C,0x9E,0x9A,0x86,0x86,0x2A,0x36,0xA0, + 0xEA,0x8C,0x02,0x02,0xE1,0xEE,0x79,0x7B,0xFB, + 0x7E,0x65,0x0C,0x13,0x24,0x9A,0x1D,0xBF,0xBE, + 0x42,0x85,0x18,0x72,0x65,0x0E,0x14,0x05,0xCE, + 0x5E,0xA5,0x16,0x72,0x45,0x00,0x3C,0x55,0x8A, + 0xB9,0x0B,0xAA,0x48,0x86,0x8A,0x40,0xE0,0x9C, + 0xC5,0x49,0xA0,0x31,0x00,0x07,0x00,0xA5,0x6A, + 0x7E,0xC4,0x10,0x72,0xA4,0x80,0x08,0xC7,0xC2, + 0x0A,0x47,0x12,0x03,0x81,0x00,0x6C,0xC0,0xFE, + 0x1A,0xC7,0x9E,0x03,0xE0,0x81,0x68,0xA0,0xB4, + 0x06,0xC5,0x10,0x33,0x63,0x88,0x60,0x31,0xB6, + 0x1A,0xE4,0x1A,0x13,0xE1,0x0E,0x4C,0x50,0xB8, + 0x9A,0xA1,0xC8,0x28,0xE0,0x72,0x0D,0xAE,0xD8, + 0x92,0x30,0xC9,0x7B,0x5B,0x4F,0x5D,0x6D,0xBE, + 0xCE,0x94,0xD9,0xC8,0xDF,0x4F,0xAC,0xC8,0x12, + 0xCB,0x13,0xCF,0xE6,0x4C,0x8C,0xEB,0x6F,0xD7, + 0xEB,0x17,0xE5,0x10,0x9B,0xD6,0xE8,0xC4,0xAF, + 0x8B,0xD1,0xAC,0x7B,0xCA,0x5F,0x12,0xA4,0xAF, + 0x8E,0xD3,0xA2,0x71,0x95,0xF8,0x8E,0x7E,0xCA, + 0x3B,0x44,0x1C,0x23,0x75,0xFE,0xDF,0xD5,0x7A, + 0x33,0x43,0x96,0x32,0x30,0xE4,0xB0,0xA6,0x96, + 0x4F,0xE1,0x18,0x63,0xB6,0x26,0xD8,0xE1,0x6A, + 0x6F,0xC7,0x16,0x62,0xE3,0xFA,0x97,0x91,0x82, + 0xF1,0xC7,0x8C,0xFB,0x86,0xE3,0xCE,0x75,0xB2, + 0xA3,0x92,0x38,0xDB,0x45,0xF8,0x88,0x75,0xBE, + 0x02,0xE3,0x16,0x5B,0x46,0xBC,0x5C,0x2D,0xDC, + 0xBE,0xB6,0x80,0xF9,0x03,0x90,0x2B,0x3C,0x26, + 0xF8,0x2A,0x3C,0x29,0x95,0x42,0xF9,0xA4,0xDE, + 0xC4,0x42,0x32,0xA3,0x21,0xBA,0xEF,0x07,0xB2, + 0xE8,0x88,0xBC,0x58,0xC5,0xAB,0xAE,0x8B,0xD6, + 0x0F,0x00,0x1E,0x63,0x23,0x86,0xCF,0xCB,0x9A, + 0xBB,0xF1,0x2E,0xD8,0xA7,0x58,0x07,0x86,0xDB, + 0xFD,0x0A,0x94,0xBB,0xE0,0x15,0x4D,0xD4,0x06, + 0xE1,0xB7,0xA3,0xDB,0x00,0x43,0x2A,0x5A,0xEB, + 0xF4,0x99,0x40,0x31,0xD0,0x1D,0x7B,0xDD,0x72, + 0xA5,0xD4,0x65,0x92,0x84,0xCF,0x7A,0x2F,0xD5, + 0x89,0x4A,0x80,0x9B,0xF5,0xC6,0x0C,0xAA,0x84, + 0x88,0x30,0xF8,0xB0,0xB5,0xC5,0x19,0x48,0x1A, + 0xFC,0xE5,0x3C,0x59,0x41,0x03,0x28,0xF2,0x9C, + 0x99,0xC9,0x26,0x58,0xE6,0x09,0x6C,0x61,0xD8, + 0x99,0xE8,0xAA,0x78,0x85,0x0F,0x64,0x32,0x92, + 0x5E,0xC7,0x18,0x52,0xC4,0x05,0x3C,0xA6,0x8A, + 0x0E,0xC4,0x94,0x3B,0x22,0x03,0x60,0x60,0x70, +}; + +#endif /* dmrtodstarsample_h */